(function UMDish(name, context, definition) {
	context[name] = definition.call(context);
	if (typeof module !== 'undefined' && module.exports) {
		module.exports = context[name];
	} else if (typeof define === 'function' && define.amd) {
		define(function reference() {
			return context[name];
		});
	}
})('Primus', this, function wrapper() {
	var define,
		module,
		exports,
		Primus = (function e(t, n, r) {
			function s(o, u) {
				if (!n[o]) {
					if (!t[o]) {
						var a = typeof require == 'function' && require;
						if (!u && a) return a(o, !0);
						if (i) return i(o, !0);
						var f = new Error("Cannot find module '" + o + "'");
						throw ((f.code = 'MODULE_NOT_FOUND'), f);
					}
					var l = (n[o] = { exports: {} });
					t[o][0].call(
						l.exports,
						function(e) {
							var n = t[o][1][e];
							return s(n ? n : e);
						},
						l,
						l.exports,
						e,
						t,
						n,
						r
					);
				}
				return n[o].exports;
			}
			var i = typeof require == 'function' && require;
			for (var o = 0; o < r.length; o++) s(r[o]);
			return s;
		})(
			{
				1: [
					function(_dereq_, module, exports) {
						'use strict';

						/**
 * Create a function that will cleanup the instance.
 *
 * @param {Array|String} keys Properties on the instance that needs to be cleared.
 * @param {Object} options Additional configuration.
 * @returns {Function} Destroy function
 * @api public
 */
						module.exports = function demolish(keys, options) {
							var split = /[, ]+/;

							options = options || {};
							keys = keys || [];

							if ('string' === typeof keys) keys = keys.split(split);

							/**
   * Run addition cleanup hooks.
   *
   * @param {String} key Name of the clean up hook to run.
   * @param {Mixed} selfie Reference to the instance we're cleaning up.
   * @api private
   */
							function run(key, selfie) {
								if (!options[key]) return;
								if ('string' === typeof options[key])
									options[key] = options[key].split(split);
								if ('function' === typeof options[key])
									return options[key].call(selfie);

								for (var i = 0, type, what; i < options[key].length; i++) {
									what = options[key][i];
									type = typeof what;

									if ('function' === type) {
										what.call(selfie);
									} else if (
										'string' === type &&
										'function' === typeof selfie[what]
									) {
										selfie[what]();
									}
								}
							}

							/**
   * Destroy the instance completely and clean up all the existing references.
   *
   * @returns {Boolean}
   * @api public
   */
							return function destroy() {
								var selfie = this,
									i = 0,
									prop;

								if (selfie[keys[0]] === null) return false;
								run('before', selfie);

								for (; i < keys.length; i++) {
									prop = keys[i];

									if (selfie[prop]) {
										if ('function' === typeof selfie[prop].destroy)
											selfie[prop].destroy();
										selfie[prop] = null;
									}
								}

								if (selfie.emit) selfie.emit('destroy');
								run('after', selfie);

								return true;
							};
						};
					},
					{},
				],
				2: [
					function(_dereq_, module, exports) {
						'use strict';

						/**
 * Returns a function that when invoked executes all the listeners of the
 * given event with the given arguments.
 *
 * @returns {Function} The function that emits all the things.
 * @api public
 */
						module.exports = function emits() {
							var self = this,
								parser;

							for (
								var i = 0, l = arguments.length, args = new Array(l);
								i < l;
								i++
							) {
								args[i] = arguments[i];
							}

							//
							// If the last argument is a function, assume that it's a parser.
							//
							if ('function' !== typeof args[args.length - 1])
								return function emitter() {
									for (
										var i = 0, l = arguments.length, arg = new Array(l);
										i < l;
										i++
									) {
										arg[i] = arguments[i];
									}

									return self.emit.apply(self, args.concat(arg));
								};

							parser = args.pop();

							/**
   * The actual function that emits the given event. It returns a boolean
   * indicating if the event was emitted.
   *
   * @returns {Boolean}
   * @api public
   */
							return function emitter() {
								for (
									var i = 0, l = arguments.length, arg = new Array(l + 1);
									i < l;
									i++
								) {
									arg[i + 1] = arguments[i];
								}

								/**
     * Async completion method for the parser.
     *
     * @param {Error} err Optional error when parsing failed.
     * @param {Mixed} returned Emit instructions.
     * @api private
     */
								arg[0] = function next(err, returned) {
									if (err) return self.emit('error', err);

									arg = returned === undefined
										? arg.slice(1)
										: returned === null ? [] : returned;

									self.emit.apply(self, args.concat(arg));
								};

								parser.apply(self, arg);
								return true;
							};
						};
					},
					{},
				],
				3: [
					function(_dereq_, module, exports) {
						'use strict';

						/**
 * Representation of a single EventEmitter function.
 *
 * @param {Function} fn Event handler to be called.
 * @param {Mixed} context Context for function execution.
 * @param {Boolean} once Only emit once
 * @api private
 */
						function EE(fn, context, once) {
							this.fn = fn;
							this.context = context;
							this.once = once || false;
						}

						/**
 * Minimal EventEmitter interface that is molded against the Node.js
 * EventEmitter interface.
 *
 * @constructor
 * @api public
 */
						function EventEmitter() {
							/* Nothing to set */
						}

						/**
 * Holds the assigned EventEmitters by name.
 *
 * @type {Object}
 * @private
 */
						EventEmitter.prototype._events = undefined;

						/**
 * Return a list of assigned event listeners.
 *
 * @param {String} event The events that should be listed.
 * @returns {Array}
 * @api public
 */
						EventEmitter.prototype.listeners = function listeners(event) {
							if (!this._events || !this._events[event]) return [];
							if (this._events[event].fn) return [this._events[event].fn];

							for (
								var i = 0, l = this._events[event].length, ee = new Array(l);
								i < l;
								i++
							) {
								ee[i] = this._events[event][i].fn;
							}

							return ee;
						};

						/**
 * Emit an event to all registered event listeners.
 *
 * @param {String} event The name of the event.
 * @returns {Boolean} Indication if we've emitted an event.
 * @api public
 */
						EventEmitter.prototype.emit = function emit(
							event,
							a1,
							a2,
							a3,
							a4,
							a5
						) {
							if (!this._events || !this._events[event]) return false;

							var listeners = this._events[event],
								len = arguments.length,
								args,
								i;

							if ('function' === typeof listeners.fn) {
								if (listeners.once)
									this.removeListener(event, listeners.fn, true);

								switch (len) {
									case 1:
										return listeners.fn.call(listeners.context), true;
									case 2:
										return listeners.fn.call(listeners.context, a1), true;
									case 3:
										return listeners.fn.call(listeners.context, a1, a2), true;
									case 4:
										return listeners.fn.call(
											listeners.context,
											a1,
											a2,
											a3
										), true;
									case 5:
										return listeners.fn.call(
											listeners.context,
											a1,
											a2,
											a3,
											a4
										), true;
									case 6:
										return listeners.fn.call(
											listeners.context,
											a1,
											a2,
											a3,
											a4,
											a5
										), true;
								}

								for (i = 1, args = new Array(len - 1); i < len; i++) {
									args[i - 1] = arguments[i];
								}

								listeners.fn.apply(listeners.context, args);
							} else {
								var length = listeners.length,
									j;

								for (i = 0; i < length; i++) {
									if (listeners[i].once)
										this.removeListener(event, listeners[i].fn, true);

									switch (len) {
										case 1:
											listeners[i].fn.call(listeners[i].context);
											break;
										case 2:
											listeners[i].fn.call(listeners[i].context, a1);
											break;
										case 3:
											listeners[i].fn.call(listeners[i].context, a1, a2);
											break;
										default:
											if (!args)
												for (j = 1, args = new Array(len - 1); j < len; j++) {
													args[j - 1] = arguments[j];
												}

											listeners[i].fn.apply(listeners[i].context, args);
									}
								}
							}

							return true;
						};

						/**
 * Register a new EventListener for the given event.
 *
 * @param {String} event Name of the event.
 * @param {Functon} fn Callback function.
 * @param {Mixed} context The context of the function.
 * @api public
 */
						EventEmitter.prototype.on = function on(event, fn, context) {
							var listener = new EE(fn, context || this);

							if (!this._events) this._events = {};
							if (!this._events[event]) this._events[event] = listener;
							else {
								if (!this._events[event].fn) this._events[event].push(listener);
								else this._events[event] = [this._events[event], listener];
							}

							return this;
						};

						/**
 * Add an EventListener that's only called once.
 *
 * @param {String} event Name of the event.
 * @param {Function} fn Callback function.
 * @param {Mixed} context The context of the function.
 * @api public
 */
						EventEmitter.prototype.once = function once(event, fn, context) {
							var listener = new EE(fn, context || this, true);

							if (!this._events) this._events = {};
							if (!this._events[event]) this._events[event] = listener;
							else {
								if (!this._events[event].fn) this._events[event].push(listener);
								else this._events[event] = [this._events[event], listener];
							}

							return this;
						};

						/**
 * Remove event listeners.
 *
 * @param {String} event The event we want to remove.
 * @param {Function} fn The listener that we need to find.
 * @param {Boolean} once Only remove once listeners.
 * @api public
 */
						EventEmitter.prototype.removeListener = function removeListener(
							event,
							fn,
							once
						) {
							if (!this._events || !this._events[event]) return this;

							var listeners = this._events[event],
								events = [];

							if (fn) {
								if (
									listeners.fn &&
									(listeners.fn !== fn || (once && !listeners.once))
								) {
									events.push(listeners);
								}
								if (!listeners.fn)
									for (var i = 0, length = listeners.length; i < length; i++) {
										if (
											listeners[i].fn !== fn ||
											(once && !listeners[i].once)
										) {
											events.push(listeners[i]);
										}
									}
							}

							//
							// Reset the array, or remove it completely if we have no more listeners.
							//
							if (events.length) {
								this._events[event] = events.length === 1 ? events[0] : events;
							} else {
								delete this._events[event];
							}

							return this;
						};

						/**
 * Remove all listeners or only the listeners for the specified event.
 *
 * @param {String} event The event want to remove all listeners for.
 * @api public
 */
						EventEmitter.prototype.removeAllListeners = function removeAllListeners(
							event
						) {
							if (!this._events) return this;

							if (event) delete this._events[event];
							else this._events = {};

							return this;
						};

						//
						// Alias methods names because people roll like that.
						//
						EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
						EventEmitter.prototype.addListener = EventEmitter.prototype.on;

						//
						// This function doesn't apply anymore.
						//
						EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
							return this;
						};

						//
						// Expose the module.
						//
						EventEmitter.EventEmitter = EventEmitter;
						EventEmitter.EventEmitter2 = EventEmitter;
						EventEmitter.EventEmitter3 = EventEmitter;

						//
						// Expose the module.
						//
						module.exports = EventEmitter;
					},
					{},
				],
				4: [
					function(_dereq_, module, exports) {
						'use strict';

						var has = Object.prototype.hasOwnProperty;

						/**
 * Simple query string parser.
 *
 * @param {String} query The query string that needs to be parsed.
 * @returns {Object}
 * @api public
 */
						function querystring(query) {
							var parser = /([^=?&]+)=([^&]*)/g,
								result = {},
								part;

							//
							// Little nifty parsing hack, leverage the fact that RegExp.exec increments
							// the lastIndex property so we can continue executing this loop until we've
							// parsed all results.
							//
							for (
								;
								(part = parser.exec(query));
								result[decodeURIComponent(part[1])] = decodeURIComponent(
									part[2]
								)
							);

							return result;
						}

						/**
 * Transform a query string to an object.
 *
 * @param {Object} obj Object that should be transformed.
 * @param {String} prefix Optional prefix.
 * @returns {String}
 * @api public
 */
						function querystringify(obj, prefix) {
							prefix = prefix || '';

							var pairs = [];

							//
							// Optionally prefix with a '?' if needed
							//
							if ('string' !== typeof prefix) prefix = '?';

							for (var key in obj) {
								if (has.call(obj, key)) {
									pairs.push(
										encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])
									);
								}
							}

							return prefix + pairs.join('&');
						}

						//
						// Expose the module.
						//
						exports.stringify = querystringify;
						exports.parse = querystring;
					},
					{},
				],
				5: [
					function(_dereq_, module, exports) {
						'use strict';

						var EventEmitter = _dereq_('eventemitter3'),
							millisecond = _dereq_('millisecond'),
							destroy = _dereq_('demolish'),
							Tick = _dereq_('tick-tock'),
							one = _dereq_('one-time');

						/**
 * Returns sane defaults about a given value.
 *
 * @param {String} name Name of property we want.
 * @param {Recovery} selfie Recovery instance that got created.
 * @param {Object} opts User supplied options we want to check.
 * @returns {Number} Some default value.
 * @api private
 */
						function defaults(name, selfie, opts) {
							return millisecond(
								name in opts
									? opts[name]
									: name in selfie ? selfie[name] : Recovery[name]
							);
						}

						/**
 * Attempt to recover your connection with reconnection attempt.
 *
 * @constructor
 * @param {Object} options Configuration
 * @api public
 */
						function Recovery(options) {
							var recovery = this;

							if (!(recovery instanceof Recovery)) return new Recovery(options);

							options = options || {};

							recovery.attempt = null; // Stores the current reconnect attempt.
							recovery._fn = null; // Stores the callback.

							recovery['reconnect timeout'] = defaults(
								'reconnect timeout',
								recovery,
								options
							);
							recovery.retries = defaults('retries', recovery, options);
							recovery.factor = defaults('factor', recovery, options);
							recovery.max = defaults('max', recovery, options);
							recovery.min = defaults('min', recovery, options);
							recovery.timers = new Tick(recovery);
						}

						Recovery.prototype = new EventEmitter();
						Recovery.prototype.constructor = Recovery;

						Recovery['reconnect timeout'] = '30 seconds'; // Maximum time to wait for an answer.
						Recovery.max = Infinity; // Maximum delay.
						Recovery.min = '500 ms'; // Minimum delay.
						Recovery.retries = 10; // Maximum amount of retries.
						Recovery.factor = 2; // Exponential back off factor.

						/**
 * Start a new reconnect procedure.
 *
 * @returns {Recovery}
 * @api public
 */
						Recovery.prototype.reconnect = function reconnect() {
							var recovery = this;

							return recovery.backoff(function backedoff(err, opts) {
								opts.duration = +new Date() - opts.start;

								if (err) return recovery.emit('reconnect failed', err, opts);

								recovery.emit('reconnected', opts);
							}, recovery.attempt);
						};

						/**
 * Exponential back off algorithm for retry operations. It uses a randomized
 * retry so we don't DDOS our server when it goes down under pressure.
 *
 * @param {Function} fn Callback to be called after the timeout.
 * @param {Object} opts Options for configuring the timeout.
 * @returns {Recovery}
 * @api private
 */
						Recovery.prototype.backoff = function backoff(fn, opts) {
							var recovery = this;

							opts = opts || recovery.attempt || {};

							//
							// Bailout when we already have a back off process running. We shouldn't call
							// the callback then.
							//
							if (opts.backoff) return recovery;

							opts['reconnect timeout'] = defaults(
								'reconnect timeout',
								recovery,
								opts
							);
							opts.retries = defaults('retries', recovery, opts);
							opts.factor = defaults('factor', recovery, opts);
							opts.max = defaults('max', recovery, opts);
							opts.min = defaults('min', recovery, opts);

							opts.start = +opts.start || +new Date();
							opts.duration = +opts.duration || 0;
							opts.attempt = +opts.attempt || 0;

							//
							// Bailout if we are about to make too much attempts.
							//
							if (opts.attempt === opts.retries) {
								fn.call(recovery, new Error('Unable to recover'), opts);
								return recovery;
							}

							//
							// Prevent duplicate back off attempts using the same options object and
							// increment our attempt as we're about to have another go at this thing.
							//
							opts.backoff = true;
							opts.attempt++;

							recovery.attempt = opts;

							//
							// Calculate the timeout, but make it randomly so we don't retry connections
							// at the same interval and defeat the purpose. This exponential back off is
							// based on the work of:
							//
							// http://dthain.blogspot.nl/2009/02/exponential-backoff-in-distributed.html
							//
							opts.scheduled = opts.attempt !== 1
								? Math.min(
										Math.round(
											(Math.random() + 1) *
												opts.min *
												Math.pow(opts.factor, opts.attempt - 1)
										),
										opts.max
									)
								: opts.min;

							recovery.timers.setTimeout(
								'reconnect',
								function delay() {
									opts.duration = +new Date() - opts.start;
									opts.backoff = false;
									recovery.timers.clear('reconnect, timeout');

									//
									// Create a `one` function which can only be called once. So we can use the
									// same function for different types of invocations to create a much better
									// and usable API.
									//
									var connect = (recovery._fn = one(function connect(err) {
										recovery.reset();

										if (err) return recovery.backoff(fn, opts);

										fn.call(recovery, undefined, opts);
									}));

									recovery.emit('reconnect', opts, connect);
									recovery.timers.setTimeout(
										'timeout',
										function timeout() {
											var err = new Error(
												'Failed to reconnect in a timely manner'
											);
											opts.duration = +new Date() - opts.start;

											recovery.emit('reconnect timeout', err, opts);
											connect(err);
										},
										opts['reconnect timeout']
									);
								},
								opts.scheduled
							);

							//
							// Emit a `reconnecting` event with current reconnect options. This allows
							// them to update the UI and provide their users with feedback.
							//
							recovery.emit('reconnect scheduled', opts);

							return recovery;
						};

						/**
 * Check if the reconnection process is currently reconnecting.
 *
 * @returns {Boolean}
 * @api public
 */
						Recovery.prototype.reconnecting = function reconnecting() {
							return !!this.attempt;
						};

						/**
 * Tell our reconnection procedure that we're passed.
 *
 * @param {Error} err Reconnection failed.
 * @returns {Recovery}
 * @api public
 */
						Recovery.prototype.reconnected = function reconnected(err) {
							if (this._fn) this._fn(err);
							return this;
						};

						/**
 * Reset the reconnection attempt so it can be re-used again.
 *
 * @returns {Recovery}
 * @api public
 */
						Recovery.prototype.reset = function reset() {
							this._fn = this.attempt = null;
							this.timers.clear('reconnect, timeout');

							return this;
						};

						/**
 * Clean up the instance.
 *
 * @type {Function}
 * @returns {Boolean}
 * @api public
 */
						Recovery.prototype.destroy = destroy('timers attempt _fn');

						//
						// Expose the module.
						//
						module.exports = Recovery;
					},
					{
						demolish: 1,
						eventemitter3: 3,
						millisecond: 6,
						'one-time': 7,
						'tick-tock': 8,
					},
				],
				6: [
					function(_dereq_, module, exports) {
						/**
 * Parse a time string and return the number value of it.
 *
 * @param {String} ms Time string.
 * @returns {Number}
 * @api private
 */
						module.exports = function millisecond(ms) {
							'use strict';

							if ('string' !== typeof ms || '0' === ms || +ms) return +ms;

							var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
									ms
								),
								second = 1000,
								minute = second * 60,
								hour = minute * 60,
								day = hour * 24,
								amount;

							if (!match) return 0;

							amount = parseFloat(match[1]);

							switch (match[2].toLowerCase()) {
								case 'days':
								case 'day':
								case 'd':
									return amount * day;

								case 'hours':
								case 'hour':
								case 'hrs':
								case 'hr':
								case 'h':
									return amount * hour;

								case 'minutes':
								case 'minute':
								case 'mins':
								case 'min':
								case 'm':
									return amount * minute;

								case 'seconds':
								case 'second':
								case 'secs':
								case 'sec':
								case 's':
									return amount * second;

								default:
									return amount;
							}
						};
					},
					{},
				],
				7: [
					function(_dereq_, module, exports) {
						'use strict';

						/**
 * Wrap callbacks to prevent double execution.
 *
 * @param {Function} fn Function that should only be called once.
 * @returns {Function} A wrapped callback which prevents execution.
 * @api public
 */
						module.exports = function one(fn) {
							var called = false,
								value;

							return function time() {
								if (called) return value;

								called = true;
								value = fn.apply(this, arguments);
								fn = null;

								return value;
							};
						};
					},
					{},
				],
				8: [
					function(_dereq_, module, exports) {
						'use strict';

						var has = Object.prototype.hasOwnProperty,
							ms = _dereq_('millisecond');

						/**
 * Simple timer management.
 *
 * @constructor
 * @param {Mixed} context Context of the callbacks that we execute.
 * @api public
 */
						function Tick(context) {
							if (!(this instanceof Tick)) return new Tick(context);

							this.timers = {};
							this.context = context || this;
						}

						/**
 * Return a function which will just iterate over all assigned callbacks and
 * optionally clear the timers from memory if needed.
 *
 * @param {String} name Name of the timer we need to execute.
 * @param {Boolean} clear Also clear from memory.
 * @returns {Function}
 * @api private
 */
						Tick.prototype.tock = function ticktock(name, clear) {
							var tock = this;

							return function tickedtock() {
								if (!(name in tock.timers)) return;

								var timer = tock.timers[name],
									fns = timer.fns.slice(),
									l = fns.length,
									i = 0;

								if (clear) tock.clear(name);

								for (; i < l; i++) {
									fns[i].call(tock.context);
								}
							};
						};

						/**
 * Add a new timeout.
 *
 * @param {String} name Name of the timer.
 * @param {Function} fn Completion callback.
 * @param {Mixed} time Duration of the timer.
 * @returns {Tick}
 * @api public
 */
						Tick.prototype.setTimeout = function timeout(name, fn, time) {
							var tick = this;

							if (tick.timers[name]) {
								tick.timers[name].fns.push(fn);
								return tick;
							}

							tick.timers[name] = {
								timer: setTimeout(tick.tock(name, true), ms(time)),
								clear: function clear(id) {
									clearTimeout(id);
								},
								fns: [fn],
							};

							return tick;
						};

						/**
 * Add a new interval.
 *
 * @param {String} name Name of the timer.
 * @param {Function} fn Completion callback.
 * @param {Mixed} time Interval of the timer.
 * @returns {Tick}
 * @api public
 */
						Tick.prototype.setInterval = function interval(name, fn, time) {
							var tick = this;

							if (tick.timers[name]) {
								tick.timers[name].fns.push(fn);
								return tick;
							}

							tick.timers[name] = {
								timer: setInterval(tick.tock(name), ms(time)),
								clear: function clear(id) {
									clearInterval(id);
								},
								fns: [fn],
							};

							return tick;
						};

						/**
 * Add a new setImmediate.
 *
 * @param {String} name Name of the timer.
 * @param {Function} fn Completion callback.
 * @returns {Tick}
 * @api public
 */
						Tick.prototype.setImmediate = function immediate(name, fn) {
							var tick = this;

							if ('function' !== typeof setImmediate)
								return tick.setTimeout(name, fn, 0);

							if (tick.timers[name]) {
								tick.timers[name].fns.push(fn);
								return tick;
							}

							tick.timers[name] = {
								timer: setImmediate(tick.tock(name, true)),
								clear: function clear(id) {
									clearImmediate(id);
								},
								fns: [fn],
							};

							return tick;
						};

						/**
 * Check if we have a timer set.
 *
 * @param {String} name
 * @returns {Boolean}
 * @api public
 */
						Tick.prototype.active = function active(name) {
							return name in this.timers;
						};

						/**
 * Properly clean up all timeout references. If no arguments are supplied we
 * will attempt to clear every single timer that is present.
 *
 * @param {Arguments} ..args.. The names of the timeouts we need to clear
 * @returns {Tick}
 * @api public
 */
						Tick.prototype.clear = function clear() {
							var args = arguments.length ? arguments : [],
								tick = this,
								timer,
								i,
								l;

							if (args.length === 1 && 'string' === typeof args[0]) {
								args = args[0].split(/[, ]+/);
							}

							if (!args.length) {
								for (timer in tick.timers) {
									if (has.call(tick.timers, timer)) args.push(timer);
								}
							}

							for (i = 0, l = args.length; i < l; i++) {
								timer = tick.timers[args[i]];

								if (!timer) continue;
								timer.clear(timer.timer);

								timer.fns = timer.timer = timer.clear = null;
								delete tick.timers[args[i]];
							}

							return tick;
						};

						/**
 * We will no longer use this module, prepare your self for global cleanups.
 *
 * @returns {Boolean}
 * @api public
 */
						Tick.prototype.end = Tick.prototype.destroy = function end() {
							if (!this.context) return false;

							this.clear();
							this.context = this.timers = null;

							return true;
						};

						/**
 * Adjust a timeout or interval to a new duration.
 *
 * @returns {Tick}
 * @api public
 */
						Tick.prototype.adjust = function adjust(name, time) {
							var interval,
								tick = this,
								timer = tick.timers[name];

							if (!timer) return tick;

							interval = timer.clear === clearInterval;
							timer.clear(timer.timer);
							timer.timer = (interval ? setInterval : setTimeout)(
								tick.tock(name, !interval),
								ms(time)
							);

							return tick;
						};

						//
						// Expose the timer factory.
						//
						module.exports = Tick;
					},
					{ millisecond: 9 },
				],
				9: [
					function(_dereq_, module, exports) {
						arguments[4][6][0].apply(exports, arguments);
					},
					{ dup: 6 },
				],
				10: [
					function(_dereq_, module, exports) {
						/*globals require, define */
						'use strict';

						var EventEmitter = _dereq_('eventemitter3'),
							TickTock = _dereq_('tick-tock'),
							Recovery = _dereq_('recovery'),
							qs = _dereq_('querystringify'),
							destroy = _dereq_('demolish');

						/**
 * Context assertion, ensure that some of our public Primus methods are called
 * with the correct context to ensure that
 *
 * @param {Primus} self The context of the function.
 * @param {String} method The method name.
 * @api private
 */
						function context(self, method) {
							if (self instanceof Primus) return;

							var failure = new Error(
								'Primus#' +
									method +
									"'s context should called with a Primus instance"
							);

							if (
								'function' !== typeof self.listeners ||
								!self.listeners('error').length
							) {
								throw failure;
							}

							self.emit('error', failure);
						}

						//
						// Sets the default connection URL, it uses the default origin of the browser
						// when supported but degrades for older browsers. In Node.js, we cannot guess
						// where the user wants to connect to, so we just default to localhost.
						//
						var defaultUrl;

						try {
							if (location.origin) {
								defaultUrl = location.origin;
							} else {
								defaultUrl =
									location.protocol +
									'//' +
									location.hostname +
									(location.port ? ':' + location.port : '');
							}
						} catch (e) {
							defaultUrl = 'http://127.0.0.1';
						}

						/**
 * Primus in a real-time library agnostic framework for establishing real-time
 * connections with servers.
 *
 * Options:
 * - reconnect, configuration for the reconnect process.
 * - manual, don't automatically call `.open` to start the connection.
 * - websockets, force the use of WebSockets, even when you should avoid them.
 * - timeout, connect timeout, server didn't respond in a timely manner.
 * - ping, The heartbeat interval for sending a ping packet to the server.
 * - pong, The heartbeat timeout for receiving a response to the ping.
 * - network, Use network events as leading method for network connection drops.
 * - strategy, Reconnection strategies.
 * - transport, Transport options.
 * - url, uri, The URL to use connect with the server.
 *
 * @constructor
 * @param {String} url The URL of your server.
 * @param {Object} options The configuration.
 * @api public
 */
						function Primus(url, options) {
							if (!(this instanceof Primus)) return new Primus(url, options);
							if ('function' !== typeof this.client) {
								var message =
									'The client library has not been compiled correctly, ' +
									'see https://github.com/primus/primus#client-library for more details';
								return this.critical(new Error(message));
							}

							if ('object' === typeof url) {
								options = url;
								url = options.url || options.uri || defaultUrl;
							} else {
								options = options || {};
							}

							var primus = this;

							// The maximum number of messages that can be placed in queue.
							options.queueSize = 'queueSize' in options
								? options.queueSize
								: Infinity;

							// Connection timeout duration.
							options.timeout = 'timeout' in options ? options.timeout : 10e3;

							// Stores the back off configuration.
							options.reconnect = 'reconnect' in options
								? options.reconnect
								: {};

							// Heartbeat ping interval.
							options.ping = 'ping' in options ? options.ping : 25000;

							// Heartbeat pong response timeout.
							options.pong = 'pong' in options ? options.pong : 10e3;

							// Reconnect strategies.
							options.strategy = 'strategy' in options ? options.strategy : [];

							// Custom transport options.
							options.transport = 'transport' in options
								? options.transport
								: {};

							primus.buffer = []; // Stores premature send data.
							primus.writable = true; // Silly stream compatibility.
							primus.readable = true; // Silly stream compatibility.
							primus.url = primus.parse(url || defaultUrl); // Parse the URL to a readable format.
							primus.readyState = Primus.CLOSED; // The readyState of the connection.
							primus.options = options; // Reference to the supplied options.
							primus.timers = new TickTock(this); // Contains all our timers.
							primus.socket = null; // Reference to the internal connection.
							primus.latency = 0; // Latency between messages.
							primus.stamps = 0; // Counter to make timestamps unique.
							primus.disconnect = false; // Did we receive a disconnect packet?
							primus.transport = options.transport; // Transport options.
							primus.transformers = {
								// Message transformers.
								outgoing: [],
								incoming: [],
							};

							//
							// Create our reconnection instance.
							//
							primus.recovery = new Recovery(options.reconnect);

							//
							// Parse the reconnection strategy. It can have the following strategies:
							//
							// - timeout: Reconnect when we have a network timeout.
							// - disconnect: Reconnect when we have an unexpected disconnect.
							// - online: Reconnect when we're back online.
							//
							if ('string' === typeof options.strategy) {
								options.strategy = options.strategy.split(/\s?\,\s?/g);
							}

							if (false === options.strategy) {
								//
								// Strategies are disabled, but we still need an empty array to join it in
								// to nothing.
								//
								options.strategy = [];
							} else if (!options.strategy.length) {
								options.strategy.push('disconnect', 'online');

								//
								// Timeout based reconnection should only be enabled conditionally. When
								// authorization is enabled it could trigger.
								//
								if (!this.authorization) options.strategy.push('timeout');
							}

							options.strategy = options.strategy.join(',').toLowerCase();

							//
							// Force the use of WebSockets, even when we've detected some potential
							// broken WebSocket implementation.
							//
							if ('websockets' in options) {
								primus.AVOID_WEBSOCKETS = !options.websockets;
							}

							//
							// Force or disable the use of NETWORK events as leading client side
							// disconnection detection.
							//
							if ('network' in options) {
								primus.NETWORK_EVENTS = options.network;
							}

							//
							// Check if the user wants to manually initialise a connection. If they don't,
							// we want to do it after a really small timeout so we give the users enough
							// time to listen for `error` events etc.
							//
							if (!options.manual)
								primus.timers.setTimeout(
									'open',
									function open() {
										primus.timers.clear('open');
										primus.open();
									},
									0
								);

							primus.initialise(options);
						}

						/**
 * Simple require wrapper to make browserify, node and require.js play nice.
 *
 * @param {String} name The module to require.
 * @returns {Object|Undefined} The module that we required.
 * @api private
 */
						Primus.require = function requires(name) {
							if ('function' !== typeof _dereq_) return undefined;

							return !('function' === typeof define && define.amd)
								? _dereq_(name)
								: undefined;
						};

						//
						// It's possible that we're running in Node.js or in a Node.js compatible
						// environment such as browserify. In these cases we want to use some build in
						// libraries to minimize our dependence on the DOM.
						//
						var Stream, parse;

						try {
							Primus.Stream = Stream = Primus.require('stream');
							parse = Primus.require('url').parse;

							//
							// Normally inheritance is done in the same way as we do in our catch
							// statement. But due to changes to the EventEmitter interface in Node 0.10
							// this will trigger annoying memory leak warnings and other potential issues
							// outlined in the issue linked below.
							//
							// @see https!://github.com/joyent/node/issues/4971
							//
							Primus.require('util').inherits(Primus, Stream);
						} catch (e) {
							Primus.Stream = EventEmitter;
							Primus.prototype = new EventEmitter();

							//
							// In the browsers we can leverage the DOM to parse the URL for us. It will
							// automatically default to host of the current server when we supply it path
							// etc.
							//
							parse = function parse(url) {
								var a = document.createElement('a'),
									data = {},
									key;

								a.href = url;

								//
								// Transform it from a readOnly object to a read/writable object so we can
								// change some parsed values. This is required if we ever want to override
								// a port number etc. (as browsers remove port 443 and 80 from the URL's).
								//
								for (key in a) {
									if (
										'string' === typeof a[key] ||
										'number' === typeof a[key]
									) {
										data[key] = a[key];
									}
								}

								//
								// We need to make sure that the URL is properly encoded because IE doesn't
								// do this automatically.
								//
								data.href = encodeURI(decodeURI(data.href));

								//
								// If we don't obtain a port number (e.g. when using zombie) then try
								// and guess at a value from the 'href' value.
								//
								if (!data.port) {
									var splits = (data.href || '').split('/');
									if (splits.length > 2) {
										var host = splits[2],
											atSignIndex = host.lastIndexOf('@');

										if (~atSignIndex) host = host.slice(atSignIndex + 1);

										splits = host.split(':');
										if (splits.length === 2) data.port = splits[1];
									}
								}

								//
								// IE quirk: The `protocol` is parsed as ":" or "" when a protocol agnostic
								// URL is used. In this case we extract the value from the `href` value.
								//
								if (!data.protocol || ':' === data.protocol) {
									data.protocol = data.href.substr(
										0,
										data.href.indexOf(':') + 1
									);
								}

								//
								// Safari 5.1.7 (windows) quirk: When parsing a URL without a port number
								// the `port` in the data object will default to "0" instead of the expected
								// "". We're going to do an explicit check on "0" and force it to "".
								//
								if ('0' === data.port) data.port = '';

								//
								// Browsers do not parse authorization information, so we need to extract
								// that from the URL.
								//
								if (~data.href.indexOf('@') && !data.auth) {
									var start = data.protocol.length + 2;
									data.auth = data.href
										.slice(start, data.href.indexOf(data.pathname, start))
										.split('@')[0];
								}

								return data;
							};
						}

						/**
 * Primus readyStates, used internally to set the correct ready state.
 *
 * @type {Number}
 * @private
 */
						Primus.OPENING = 1; // We're opening the connection.
						Primus.CLOSED = 2; // No active connection.
						Primus.OPEN = 3; // The connection is open.

						/**
 * Are we working with a potentially broken WebSockets implementation? This
 * boolean can be used by transformers to remove `WebSockets` from their
 * supported transports.
 *
 * @type {Boolean}
 * @private
 */
						Primus.prototype.AVOID_WEBSOCKETS = false;

						/**
 * Some browsers support registering emitting `online` and `offline` events when
 * the connection has been dropped on the client. We're going to detect it in
 * a simple `try {} catch (e) {}` statement so we don't have to do complicated
 * feature detection.
 *
 * @type {Boolean}
 * @private
 */
						Primus.prototype.NETWORK_EVENTS = false;
						Primus.prototype.online = true;

						try {
							if (
								(Primus.prototype.NETWORK_EVENTS =
									'onLine' in navigator &&
									(window.addEventListener || document.body.attachEvent))
							) {
								if (!navigator.onLine) {
									Primus.prototype.online = false;
								}
							}
						} catch (e) {}

						/**
 * The Ark contains all our plugins definitions. It's namespaced by
 * name => plugin.
 *
 * @type {Object}
 * @private
 */
						Primus.prototype.ark = {};

						/**
 * Simple emit wrapper that returns a function that emits an event once it's
 * called. This makes it easier for transports to emit specific events.
 *
 * @returns {Function} A function that will emit the event when called.
 * @api public
 */
						Primus.prototype.emits = _dereq_('emits');

						/**
 * A small wrapper around `emits` to add a default parser when one is not
 * supplied. The default parser will defer the emission of the event to make
 * sure that the event is emitted at the correct time.
 *
 * @returns {Function} A function that will emit the event when called.
 * @api private
 */
						Primus.prototype.trigger = function trigger() {
							for (
								var i = 0, l = arguments.length, args = new Array(l);
								i < l;
								i++
							) {
								args[i] = arguments[i];
							}

							if ('function' !== typeof args[l - 1])
								args.push(function defer(next) {
									setTimeout(next, 0);
								});

							return this.emits.apply(this, args);
						};

						/**
 * Return the given plugin.
 *
 * @param {String} name The name of the plugin.
 * @returns {Object|undefined} The plugin or undefined.
 * @api public
 */
						Primus.prototype.plugin = function plugin(name) {
							context(this, 'plugin');

							if (name) return this.ark[name];

							var plugins = {};

							for (name in this.ark) {
								plugins[name] = this.ark[name];
							}

							return plugins;
						};

						/**
 * Checks if the given event is an emitted event by Primus.
 *
 * @param {String} evt The event name.
 * @returns {Boolean} Indication of the event is reserved for internal use.
 * @api public
 */
						Primus.prototype.reserved = function reserved(evt) {
							return (
								/^(incoming|outgoing)::/.test(evt) ||
								evt in this.reserved.events
							);
						};

						/**
 * The actual events that are used by the client.
 *
 * @type {Object}
 * @public
 */
						Primus.prototype.reserved.events = {
							'reconnect scheduled': 1,
							'reconnect timeout': 1,
							readyStateChange: 1,
							'reconnect failed': 1,
							reconnected: 1,
							reconnect: 1,
							offline: 1,
							timeout: 1,
							online: 1,
							error: 1,
							close: 1,
							open: 1,
							data: 1,
							end: 1,
						};

						/**
 * Initialise the Primus and setup all parsers and internal listeners.
 *
 * @param {Object} options The original options object.
 * @returns {Primus}
 * @api private
 */
						Primus.prototype.initialise = function initialise(options) {
							var primus = this,
								start;

							primus.recovery
								.on('reconnected', primus.emits('reconnected'))
								.on(
									'reconnect failed',
									primus.emits('reconnect failed', function failed(data) {
										primus.emit('end');
										return data;
									})
								)
								.on('reconnect timeout', primus.emits('reconnect timeout'))
								.on('reconnect scheduled', primus.emits('reconnect scheduled'))
								.on(
									'reconnect',
									primus.emits('reconnect', function reconnect(next) {
										primus.emit('outgoing::reconnect');
										next();
									})
								);

							primus.on('outgoing::open', function opening() {
								var readyState = primus.readyState;

								primus.readyState = Primus.OPENING;
								if (readyState !== primus.readyState) {
									primus.emit('readyStateChange', 'opening');
								}

								start = +new Date();
							});

							primus.on('incoming::open', function opened() {
								var readyState = primus.readyState;

								if (primus.recovery.reconnecting()) {
									primus.recovery.reconnected();
								}

								//
								// The connection has been opened so we should set our state to
								// (writ|read)able so our stream compatibility works as intended.
								//
								primus.writable = true;
								primus.readable = true;

								//
								// Make sure we are flagged as `online` as we've successfully opened the
								// connection.
								//
								if (!primus.online) {
									primus.online = true;
									primus.emit('online');
								}

								primus.readyState = Primus.OPEN;
								if (readyState !== primus.readyState) {
									primus.emit('readyStateChange', 'open');
								}

								primus.latency = +new Date() - start;
								primus.timers.clear('ping', 'pong');
								primus.heartbeat();

								if (primus.buffer.length) {
									var data = primus.buffer.slice(),
										length = data.length,
										i = 0;

									primus.buffer.length = 0;

									for (; i < length; i++) {
										primus._write(data[i]);
									}
								}

								primus.emit('open');
							});

							primus.on('incoming::pong', function pong(time) {
								primus.online = true;
								primus.timers.clear('pong');
								primus.heartbeat();

								primus.latency = +new Date() - time;
							});

							primus.on('incoming::error', function error(e) {
								var connect = primus.timers.active('connect'),
									err = e;

								//
								// When the error is not an Error instance we try to normalize it.
								//
								if ('string' === typeof e) {
									err = new Error(e);
								} else if (!(e instanceof Error) && 'object' === typeof e) {
									//
									// BrowserChannel and SockJS returns an object which contains some
									// details of the error. In order to have a proper error we "copy" the
									// details in an Error instance.
									//
									err = new Error(e.message || e.reason);
									for (var key in e) {
										if (Object.prototype.hasOwnProperty.call(e, key))
											err[key] = e[key];
									}
								}
								//
								// We're still doing a reconnect attempt, it could be that we failed to
								// connect because the server was down. Failing connect attempts should
								// always emit an `error` event instead of a `open` event.
								//
								//
								if (primus.recovery.reconnecting())
									return primus.recovery.reconnected(err);
								if (primus.listeners('error').length) primus.emit('error', err);

								//
								// We received an error while connecting, this most likely the result of an
								// unauthorized access to the server.
								//
								if (connect) {
									if (~primus.options.strategy.indexOf('timeout')) {
										primus.recovery.reconnect();
									} else {
										primus.end();
									}
								}
							});

							primus.on('incoming::data', function message(raw) {
								primus.decoder(raw, function decoding(err, data) {
									//
									// Do a "save" emit('error') when we fail to parse a message. We don't
									// want to throw here as listening to errors should be optional.
									//
									if (err)
										return (
											primus.listeners('error').length &&
											primus.emit('error', err)
										);

									//
									// Handle all "primus::" prefixed protocol messages.
									//
									if (primus.protocol(data)) return;
									primus.transforms(primus, primus, 'incoming', data, raw);
								});
							});

							primus.on('incoming::end', function end() {
								var readyState = primus.readyState;

								//
								// This `end` started with the receiving of a primus::server::close packet
								// which indicated that the user/developer on the server closed the
								// connection and it was not a result of a network disruption. So we should
								// kill the connection without doing a reconnect.
								//
								if (primus.disconnect) {
									primus.disconnect = false;

									return primus.end();
								}

								//
								// Always set the readyState to closed, and if we're still connecting, close
								// the connection so we're sure that everything after this if statement block
								// is only executed because our readyState is set to `open`.
								//
								primus.readyState = Primus.CLOSED;
								if (readyState !== primus.readyState) {
									primus.emit('readyStateChange', 'end');
								}

								if (primus.timers.active('connect')) primus.end();
								if (readyState !== Primus.OPEN) {
									return primus.recovery.reconnecting()
										? primus.recovery.reconnect()
										: false;
								}

								this.writable = false;
								this.readable = false;

								//
								// Clear all timers in case we're not going to reconnect.
								//
								this.timers.clear();

								//
								// Fire the `close` event as an indication of connection disruption.
								// This is also fired by `primus#end` so it is emitted in all cases.
								//
								primus.emit('close');

								//
								// The disconnect was unintentional, probably because the server has
								// shutdown, so if the reconnection is enabled start a reconnect procedure.
								//
								if (~primus.options.strategy.indexOf('disconnect')) {
									return primus.recovery.reconnect();
								}

								primus.emit('outgoing::end');
								primus.emit('end');
							});

							//
							// Setup the real-time client.
							//
							primus.client();

							//
							// Process the potential plugins.
							//
							for (var plugin in primus.ark) {
								primus.ark[plugin].call(primus, primus, options);
							}

							//
							// NOTE: The following code is only required if we're supporting network
							// events as it requires access to browser globals.
							//
							if (!primus.NETWORK_EVENTS) return primus;

							/**
   * Handler for offline notifications.
   *
   * @api private
   */
							function offline() {
								if (!primus.online) return; // Already or still offline, bailout.

								primus.online = false;
								primus.emit('offline');
								primus.end();

								//
								// It is certainly possible that we're in a reconnection loop and that the
								// user goes offline. In this case we want to kill the existing attempt so
								// when the user goes online, it will attempt to reconnect freshly again.
								//
								primus.recovery.reset();
							}

							/**
   * Handler for online notifications.
   *
   * @api private
   */
							function online() {
								if (primus.online) return; // Already or still online, bailout.

								primus.online = true;
								primus.emit('online');

								if (~primus.options.strategy.indexOf('online')) {
									primus.recovery.reconnect();
								}
							}

							if (window.addEventListener) {
								window.addEventListener('offline', offline, false);
								window.addEventListener('online', online, false);
							} else if (document.body.attachEvent) {
								document.body.attachEvent('onoffline', offline);
								document.body.attachEvent('ononline', online);
							}

							return primus;
						};

						/**
 * Really dead simple protocol parser. We simply assume that every message that
 * is prefixed with `primus::` could be used as some sort of protocol definition
 * for Primus.
 *
 * @param {String} msg The data.
 * @returns {Boolean} Is a protocol message.
 * @api private
 */
						Primus.prototype.protocol = function protocol(msg) {
							if ('string' !== typeof msg || msg.indexOf('primus::') !== 0)
								return false;

							var last = msg.indexOf(':', 8),
								value = msg.slice(last + 2);

							switch (msg.slice(8, last)) {
								case 'pong':
									this.emit('incoming::pong', value);
									break;

								case 'server':
									//
									// The server is closing the connection, forcefully disconnect so we don't
									// reconnect again.
									//
									if ('close' === value) {
										this.disconnect = true;
									}
									break;

								case 'id':
									this.emit('incoming::id', value);
									break;

								//
								// Unknown protocol, somebody is probably sending `primus::` prefixed
								// messages.
								//
								default:
									return false;
							}

							return true;
						};

						/**
 * Execute the set of message transformers from Primus on the incoming or
 * outgoing message.
 * This function and it's content should be in sync with Spark#transforms in
 * spark.js.
 *
 * @param {Primus} primus Reference to the Primus instance with message transformers.
 * @param {Spark|Primus} connection Connection that receives or sends data.
 * @param {String} type The type of message, 'incoming' or 'outgoing'.
 * @param {Mixed} data The data to send or that has been received.
 * @param {String} raw The raw encoded data.
 * @returns {Primus}
 * @api public
 */
						Primus.prototype.transforms = function transforms(
							primus,
							connection,
							type,
							data,
							raw
						) {
							var packet = { data: data },
								fns = primus.transformers[type];

							//
							// Iterate in series over the message transformers so we can allow optional
							// asynchronous execution of message transformers which could for example
							// retrieve additional data from the server, do extra decoding or even
							// message validation.
							//
							(function transform(index, done) {
								var transformer = fns[index++];

								if (!transformer) return done();

								if (1 === transformer.length) {
									if (false === transformer.call(connection, packet)) {
										//
										// When false is returned by an incoming transformer it means that's
										// being handled by the transformer and we should not emit the `data`
										// event.
										//
										return;
									}

									return transform(index, done);
								}

								transformer.call(connection, packet, function finished(
									err,
									arg
								) {
									if (err) return connection.emit('error', err);
									if (false === arg) return;

									transform(index, done);
								});
							})(0, function done() {
								//
								// We always emit 2 arguments for the data event, the first argument is the
								// parsed data and the second argument is the raw string that we received.
								// This allows you, for example, to do some validation on the parsed data
								// and then save the raw string in your database without the stringify
								// overhead.
								//
								if ('incoming' === type)
									return connection.emit('data', packet.data, raw);

								connection._write(packet.data);
							});

							return this;
						};

						/**
 * Retrieve the current id from the server.
 *
 * @param {Function} fn Callback function.
 * @returns {Primus}
 * @api public
 */
						Primus.prototype.id = function id(fn) {
							if (this.socket && this.socket.id) return fn(this.socket.id);

							this._write('primus::id::');
							return this.once('incoming::id', fn);
						};

						/**
 * Establish a connection with the server. When this function is called we
 * assume that we don't have any open connections. If you do call it when you
 * have a connection open, it could cause duplicate connections.
 *
 * @returns {Primus}
 * @api public
 */
						Primus.prototype.open = function open() {
							context(this, 'open');

							//
							// Only start a `connection timeout` procedure if we're not reconnecting as
							// that shouldn't count as an initial connection. This should be started
							// before the connection is opened to capture failing connections and kill the
							// timeout.
							//
							if (!this.recovery.reconnecting() && this.options.timeout)
								this.timeout();

							this.emit('outgoing::open');
							return this;
						};

						/**
 * Send a new message.
 *
 * @param {Mixed} data The data that needs to be written.
 * @returns {Boolean} Always returns true as we don't support back pressure.
 * @api public
 */
						Primus.prototype.write = function write(data) {
							context(this, 'write');
							this.transforms(this, this, 'outgoing', data);

							return true;
						};

						/**
 * The actual message writer.
 *
 * @param {Mixed} data The message that needs to be written.
 * @returns {Boolean} Successful write to the underlaying transport.
 * @api private
 */
						Primus.prototype._write = function write(data) {
							var primus = this;

							//
							// The connection is closed, normally this would already be done in the
							// `spark.write` method, but as `_write` is used internally, we should also
							// add the same check here to prevent potential crashes by writing to a dead
							// socket.
							//
							if (Primus.OPEN !== primus.readyState) {
								//
								// If the buffer is at capacity, remove the first item.
								//
								if (this.buffer.length === this.options.queueSize) {
									this.buffer.splice(0, 1);
								}

								this.buffer.push(data);
								return false;
							}

							primus.encoder(data, function encoded(err, packet) {
								//
								// Do a "save" emit('error') when we fail to parse a message. We don't
								// want to throw here as listening to errors should be optional.
								//
								if (err)
									return (
										primus.listeners('error').length &&
										primus.emit('error', err)
									);
								primus.emit('outgoing::data', packet);
							});

							return true;
						};

						/**
 * Send a new heartbeat over the connection to ensure that we're still
 * connected and our internet connection didn't drop. We cannot use server side
 * heartbeats for this unfortunately.
 *
 * @returns {Primus}
 * @api private
 */
						Primus.prototype.heartbeat = function heartbeat() {
							var primus = this;

							if (!primus.options.ping) return primus;

							/**
   * Exterminate the connection as we've timed out.
   *
   * @api private
   */
							function pong() {
								primus.timers.clear('pong');

								//
								// The network events already captured the offline event.
								//
								if (!primus.online) return;

								primus.online = false;
								primus.emit('offline');
								primus.emit('incoming::end');
							}

							/**
   * We should send a ping message to the server.
   *
   * @api private
   */
							function ping() {
								var value = +new Date();

								primus.timers.clear('ping');
								primus._write('primus::ping::' + value);
								primus.emit('outgoing::ping', value);
								primus.timers.setTimeout('pong', pong, primus.options.pong);
							}

							primus.timers.setTimeout('ping', ping, primus.options.ping);
							return this;
						};

						/**
 * Start a connection timeout.
 *
 * @returns {Primus}
 * @api private
 */
						Primus.prototype.timeout = function timeout() {
							var primus = this;

							/**
   * Remove all references to the timeout listener as we've received an event
   * that can be used to determine state.
   *
   * @api private
   */
							function remove() {
								primus
									.removeListener('error', remove)
									.removeListener('open', remove)
									.removeListener('end', remove)
									.timers.clear('connect');
							}

							primus.timers.setTimeout(
								'connect',
								function expired() {
									remove(); // Clean up old references.

									if (
										primus.readyState === Primus.OPEN ||
										primus.recovery.reconnecting()
									) {
										return;
									}

									primus.emit('timeout');

									//
									// We failed to connect to the server.
									//
									if (~primus.options.strategy.indexOf('timeout')) {
										primus.recovery.reconnect();
									} else {
										primus.end();
									}
								},
								primus.options.timeout
							);

							return primus
								.on('error', remove)
								.on('open', remove)
								.on('end', remove);
						};

						/**
 * Close the connection completely.
 *
 * @param {Mixed} data last packet of data.
 * @returns {Primus}
 * @api public
 */
						Primus.prototype.end = function end(data) {
							context(this, 'end');

							if (
								this.readyState === Primus.CLOSED &&
								!this.timers.active('connect')
							) {
								//
								// If we are reconnecting stop the reconnection procedure.
								//
								if (this.recovery.reconnecting()) {
									this.recovery.reset();
									this.emit('end');
								}

								return this;
							}

							if (data !== undefined) this.write(data);

							this.writable = false;
							this.readable = false;

							var readyState = this.readyState;
							this.readyState = Primus.CLOSED;

							if (readyState !== this.readyState) {
								this.emit('readyStateChange', 'end');
							}

							this.timers.clear();
							this.emit('outgoing::end');
							this.emit('close');
							this.emit('end');

							return this;
						};

						/**
 * Completely demolish the Primus instance and forcefully nuke all references.
 *
 * @returns {Boolean}
 * @api public
 */
						Primus.prototype.destroy = destroy(
							'url timers options recovery socket transport transformers',
							{
								before: 'end',
								after: 'removeAllListeners',
							}
						);

						/**
 * Create a shallow clone of a given object.
 *
 * @param {Object} obj The object that needs to be cloned.
 * @returns {Object} Copy.
 * @api private
 */
						Primus.prototype.clone = function clone(obj) {
							return this.merge({}, obj);
						};

						/**
 * Merge different objects in to one target object.
 *
 * @param {Object} target The object where everything should be merged in.
 * @returns {Object} Original target with all merged objects.
 * @api private
 */
						Primus.prototype.merge = function merge(target) {
							var args = Array.prototype.slice.call(arguments, 1);

							for (var i = 0, l = args.length, key, obj; i < l; i++) {
								obj = args[i];

								for (key in obj) {
									if (obj.hasOwnProperty(key)) target[key] = obj[key];
								}
							}

							return target;
						};

						/**
 * Parse the connection string.
 *
 * @type {Function}
 * @param {String} url Connection URL.
 * @returns {Object} Parsed connection.
 * @api private
 */
						Primus.prototype.parse = parse;

						/**
 * Parse a query string.
 *
 * @param {String} query The query string that needs to be parsed.
 * @returns {Object} Parsed query string.
 * @api private
 */
						Primus.prototype.querystring = qs.parse;
						/**
 * Transform a query string object back into string equiv.
 *
 * @param {Object} obj The query string object.
 * @returns {String}
 * @api private
 */
						Primus.prototype.querystringify = qs.stringify;

						/**
 * Generates a connection URI.
 *
 * @param {String} protocol The protocol that should used to crate the URI.
 * @returns {String|options} The URL.
 * @api private
 */
						Primus.prototype.uri = function uri(options) {
							var url = this.url,
								server = [],
								qsa = false;

							//
							// Query strings are only allowed when we've received clearance for it.
							//
							if (options.query) qsa = true;

							options = options || {};
							options.protocol = 'protocol' in options
								? options.protocol
								: 'http';
							options.query = url.search && 'query' in options
								? url.search.charAt(0) === '?'
									? url.search.slice(1)
									: url.search
								: false;
							options.secure = 'secure' in options
								? options.secure
								: url.protocol === 'https:' || url.protocol === 'wss:';
							options.auth = 'auth' in options ? options.auth : url.auth;
							options.pathname = 'pathname' in options
								? options.pathname
								: this.pathname.slice(1);
							options.port = 'port' in options
								? +options.port
								: +url.port || (options.secure ? 443 : 80);
							options.host = 'host' in options
								? options.host
								: url.hostname || url.host.replace(':' + url.port, '');

							//
							// Allow transformation of the options before we construct a full URL from it.
							//
							this.emit('outgoing::url', options);

							//
							// `url.host` might be undefined (e.g. when using zombie) so we use the
							// hostname and port defined above.
							//
							var host = 443 !== options.port && 80 !== options.port
								? options.host + ':' + options.port
								: options.host;

							//
							// We need to make sure that we create a unique connection URL every time to
							// prevent back forward cache from becoming an issue. We're doing this by
							// forcing an cache busting query string in to the URL.
							//
							var querystring = this.querystring(options.query || '');
							querystring._primuscb = +new Date() + '-' + this.stamps++;
							options.query = this.querystringify(querystring);

							//
							// Automatically suffix the protocol so we can supply `ws` and `http` and it gets
							// transformed correctly.
							//
							server.push(
								options.secure
									? options.protocol + 's:'
									: options.protocol + ':',
								''
							);

							if (options.auth) server.push(options.auth + '@' + host);
							else server.push(host);

							//
							// Pathnames are optional as some Transformers would just use the pathname
							// directly.
							//
							if (options.pathname) server.push(options.pathname);

							//
							// Optionally add a search query.
							//
							if (qsa) server.push('?' + options.query);
							else delete options.query;

							if (options.object) return options;
							return server.join('/');
						};

						/**
 * Register a new message transformer. This allows you to easily manipulate incoming
 * and outgoing data which is particularity handy for plugins that want to send
 * meta data together with the messages.
 *
 * @param {String} type Incoming or outgoing
 * @param {Function} fn A new message transformer.
 * @returns {Primus}
 * @api public
 */
						Primus.prototype.transform = function transform(type, fn) {
							context(this, 'transform');

							if (!(type in this.transformers)) {
								return this.critical(new Error('Invalid transformer type'));
							}

							this.transformers[type].push(fn);
							return this;
						};

						/**
 * A critical error has occurred, if we have an `error` listener, emit it there.
 * If not, throw it, so we get a stack trace + proper error message.
 *
 * @param {Error} err The critical error.
 * @returns {Primus}
 * @api private
 */
						Primus.prototype.critical = function critical(err) {
							if (this.listeners('error').length) {
								this.emit('error', err);
								return this;
							}

							throw err;
						};

						/**
 * Syntax sugar, adopt a Socket.IO like API.
 *
 * @param {String} url The URL we want to connect to.
 * @param {Object} options Connection options.
 * @returns {Primus}
 * @api public
 */
						Primus.connect = function connect(url, options) {
							return new Primus(url, options);
						};

						//
						// Expose the EventEmitter so it can be re-used by wrapping libraries we're also
						// exposing the Stream interface.
						//
						Primus.EventEmitter = EventEmitter;

						//
						// These libraries are automatically are automatically inserted at the
						// server-side using the Primus#library method.
						//
						Primus.prototype.client = function client() {
							var onmessage = this.trigger('incoming::data'),
								onerror = this.trigger('incoming::error'),
								onopen = this.trigger('incoming::open'),
								onclose = this.trigger('incoming::end'),
								primus = this,
								socket;

							//
							// Select an available Engine.IO factory.
							//
							var factory = (function factory() {
								if ('undefined' !== typeof eio) return eio;

								try {
									return Primus.require('engine.io-client');
								} catch (e) {}

								return undefined;
							})();

							if (!factory)
								return primus.critical(
									new Error(
										'Missing required `engine.io-client` module. ' +
											'Please run `npm install --save engine.io-client`'
									)
								);

							//
							// Connect to the given URL.
							//
							primus.on('outgoing::open', function opening() {
								primus.emit('outgoing::end');

								primus.socket = socket = factory(
									primus.merge(
										primus.transport,
										primus.url,
										primus.uri({ protocol: 'http', query: true, object: true }),
										{
											//
											// Never remember upgrades as switching from a WIFI to a 3G connection
											// could still get your connection blocked as 3G connections are usually
											// behind a reverse proxy so ISP's can optimize mobile traffic by
											// caching requests.
											//
											rememberUpgrade: false,

											//
											// Binary support in Engine.IO breaks a shit things. Turn it off for now.
											//
											forceBase64: true,

											//
											// XDR has been the source of pain for most real-time users. It doesn't
											// support the full CORS spec and is infested with bugs. It cannot connect
											// cross-scheme, does not send ANY authorization information like Cookies,
											// Basic Authorization headers etc. Force this off by default to ensure a
											// stable connection.
											//
											enablesXDR: false,

											//
											// Force timestamps on every single connection. Engine.IO only does this
											// for polling by default, but WebSockets require an explicit `true`
											// boolean.
											//
											timestampRequests: true,
											path: this.pathname,
											transports: !primus.AVOID_WEBSOCKETS
												? ['polling', 'websocket']
												: ['polling'],
										}
									)
								);

								//
								// Nuke a growing memory leak as Engine.IO pushes instances in to an exposed
								// `sockets` array.
								//
								if (factory.sockets && factory.sockets.length) {
									factory.sockets.length = 0;
								}

								//
								// Setup the Event handlers.
								//
								socket.on('message', onmessage);
								socket.on('error', onerror);
								socket.on('close', onclose);
								socket.on('open', onopen);
							});

							//
							// We need to write a new message to the socket.
							//
							primus.on('outgoing::data', function write(message) {
								if (socket) socket.send(message);
							});

							//
							// Attempt to reconnect the socket.
							//
							primus.on('outgoing::reconnect', function reconnect() {
								primus.emit('outgoing::open');
							});

							//
							// We need to close the socket.
							//
							primus.on('outgoing::end', function close() {
								if (!socket) return;

								socket.removeListener('message', onmessage);
								socket.removeListener('error', onerror);
								socket.removeListener('close', onclose);
								socket.removeListener('open', onopen);
								socket.close();
								socket = null;
							});
						};
						Primus.prototype.authorization = false;
						Primus.prototype.pathname = '/primus';
						Primus.prototype.encoder = function encoder(data, fn) {
							var err;

							try {
								data = JSON.stringify(data);
							} catch (e) {
								err = e;
							}

							fn(err, data);
						};
						Primus.prototype.decoder = function decoder(data, fn) {
							var err;

							if ('string' !== typeof data) return fn(err, data);

							try {
								data = JSON.parse(data);
							} catch (e) {
								err = e;
							}

							fn(err, data);
						};
						Primus.prototype.version = '3.0.2';

						//
						// Hack 1: \u2028 and \u2029 are allowed inside string in JSON. But JavaScript
						// defines them as newline separators. Because no literal newlines are allowed
						// in a string this causes a ParseError. We work around this issue by replacing
						// these characters with a properly escaped version for those chars. This can
						// cause errors with JSONP requests or if the string is just evaluated.
						//
						// This could have been solved by replacing the data during the "outgoing::data"
						// event. But as it affects the JSON encoding in general I've opted for a global
						// patch instead so all JSON.stringify operations are save.
						//
						if (
							'object' === typeof JSON &&
							'function' === typeof JSON.stringify &&
							JSON.stringify(['\u2028\u2029']) === '["\u2028\u2029"]'
						) {
							JSON.stringify = (function replace(stringify) {
								var u2028 = /\u2028/g,
									u2029 = /\u2029/g;

								return function patched(value, replacer, spaces) {
									var result = stringify.call(this, value, replacer, spaces);

									//
									// Replace the bad chars.
									//
									if (result) {
										if (~result.indexOf('\u2028'))
											result = result.replace(u2028, '\\u2028');
										if (~result.indexOf('\u2029'))
											result = result.replace(u2029, '\\u2029');
									}

									return result;
								};
							})(JSON.stringify);
						}

						if (
							'undefined' !== typeof document &&
							'undefined' !== typeof navigator
						) {
							//
							// Hack 2: If you press ESC in FireFox it will close all active connections.
							// Normally this makes sense, when your page is still loading. But versions
							// before FireFox 22 will close all connections including WebSocket connections
							// after page load. One way to prevent this is to do a `preventDefault()` and
							// cancel the operation before it bubbles up to the browsers default handler.
							// It needs to be added as `keydown` event, if it's added keyup it will not be
							// able to prevent the connection from being closed.
							//
							if (document.addEventListener) {
								document.addEventListener(
									'keydown',
									function keydown(e) {
										if (e.keyCode !== 27 || !e.preventDefault) return;

										e.preventDefault();
									},
									false
								);
							}

							//
							// Hack 3: This is a Mac/Apple bug only, when you're behind a reverse proxy or
							// have you network settings set to `automatic proxy discovery` the safari
							// browser will crash when the WebSocket constructor is initialised. There is
							// no way to detect the usage of these proxies available in JavaScript so we
							// need to do some nasty browser sniffing. This only affects Safari versions
							// lower then 5.1.4
							//
							var ua = (navigator.userAgent || '').toLowerCase(),
								parsed =
									ua.match(/.+(?:rv|it|ra|ie)[\/: ](\d+)\.(\d+)(?:\.(\d+))?/) ||
									[],
								version = +[parsed[1], parsed[2]].join('.');

							if (
								!~ua.indexOf('chrome') &&
								~ua.indexOf('safari') &&
								version < 534.54
							) {
								Primus.prototype.AVOID_WEBSOCKETS = true;
							}
						}

						//
						// Expose the library.
						//
						module.exports = Primus;
					},
					{
						demolish: 1,
						emits: 2,
						eventemitter3: 3,
						querystringify: 4,
						recovery: 5,
						'tick-tock': 8,
					},
				],
			},
			{},
			[10]
		)(10);
	return Primus;
});

(function libraryWrap(Primus) {
	!(function(e) {
		var f;
		'undefined' != typeof window
			? (f = window)
			: 'undefined' != typeof self && (f = self), (f.eio = e());
	})(function() {
		var define, module, exports;
		return (function e(t, n, r) {
			function s(o, u) {
				if (!n[o]) {
					if (!t[o]) {
						var a = typeof require == 'function' && require;
						if (!u && a) return a(o, !0);
						if (i) return i(o, !0);
						var f = new Error("Cannot find module '" + o + "'");
						throw ((f.code = 'MODULE_NOT_FOUND'), f);
					}
					var l = (n[o] = { exports: {} });
					t[o][0].call(
						l.exports,
						function(e) {
							var n = t[o][1][e];
							return s(n ? n : e);
						},
						l,
						l.exports,
						e,
						t,
						n,
						r
					);
				}
				return n[o].exports;
			}
			var i = typeof require == 'function' && require;
			for (var o = 0; o < r.length; o++) s(r[o]);
			return s;
		})(
			{
				1: [
					function(_dereq_, module, exports) {
						module.exports = _dereq_('./lib/');
					},
					{ './lib/': 2 },
				],
				2: [
					function(_dereq_, module, exports) {
						module.exports = _dereq_('./socket');

						/**
 * Exports parser
 *
 * @api public
 *
 */
						module.exports.parser = _dereq_('engine.io-parser');
					},
					{ './socket': 3, 'engine.io-parser': 16 },
				],
				3: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Module dependencies.
 */

							var transports = _dereq_('./transports');
							var Emitter = _dereq_('component-emitter');
							var debug = _dereq_('debug')('engine.io-client:socket');
							var index = _dereq_('indexof');
							var parser = _dereq_('engine.io-parser');
							var parseuri = _dereq_('parseuri');
							var parsejson = _dereq_('parsejson');
							var parseqs = _dereq_('parseqs');

							/**
 * Module exports.
 */

							module.exports = Socket;

							/**
 * Noop function.
 *
 * @api private
 */

							function noop() {}

							/**
 * Socket constructor.
 *
 * @param {String|Object} uri or options
 * @param {Object} options
 * @api public
 */

							function Socket(uri, opts) {
								if (!(this instanceof Socket)) return new Socket(uri, opts);

								opts = opts || {};

								if (uri && 'object' == typeof uri) {
									opts = uri;
									uri = null;
								}

								if (uri) {
									uri = parseuri(uri);
									opts.host = uri.host;
									opts.secure =
										uri.protocol == 'https' || uri.protocol == 'wss';
									opts.port = uri.port;
									if (uri.query) opts.query = uri.query;
								}

								this.secure = null != opts.secure
									? opts.secure
									: global.location && 'https:' == location.protocol;

								if (opts.host) {
									var pieces = opts.host.split(':');
									opts.hostname = pieces.shift();
									if (pieces.length) {
										opts.port = pieces.pop();
									} else if (!opts.port) {
										// if no port is specified manually, use the protocol default
										opts.port = this.secure ? '443' : '80';
									}
								}

								this.agent = opts.agent || false;
								this.hostname =
									opts.hostname ||
									(global.location ? location.hostname : 'localhost');
								this.port =
									opts.port ||
									(global.location && location.port
										? location.port
										: this.secure ? 443 : 80);
								this.query = opts.query || {};
								if ('string' == typeof this.query)
									this.query = parseqs.decode(this.query);
								this.upgrade = false !== opts.upgrade;
								this.path =
									(opts.path || '/engine.io').replace(/\/$/, '') + '/';
								this.forceJSONP = !!opts.forceJSONP;
								this.jsonp = false !== opts.jsonp;
								this.forceBase64 = !!opts.forceBase64;
								this.enablesXDR = !!opts.enablesXDR;
								this.timestampParam = opts.timestampParam || 't';
								this.timestampRequests = opts.timestampRequests;
								this.transports = opts.transports || ['polling', 'websocket'];
								this.readyState = '';
								this.writeBuffer = [];
								this.callbackBuffer = [];
								this.policyPort = opts.policyPort || 843;
								this.rememberUpgrade = opts.rememberUpgrade || false;
								this.binaryType = null;
								this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;

								// SSL options for Node.js client
								this.pfx = opts.pfx || null;
								this.key = opts.key || null;
								this.passphrase = opts.passphrase || null;
								this.cert = opts.cert || null;
								this.ca = opts.ca || null;
								this.ciphers = opts.ciphers || null;
								this.rejectUnauthorized = opts.rejectUnauthorized || null;

								this.open();
							}

							Socket.priorWebsocketSuccess = false;

							/**
 * Mix in `Emitter`.
 */

							Emitter(Socket.prototype);

							/**
 * Protocol version.
 *
 * @api public
 */

							Socket.protocol = parser.protocol; // this is an int

							/**
 * Expose deps for legacy compatibility
 * and standalone browser access.
 */

							Socket.Socket = Socket;
							Socket.Transport = _dereq_('./transport');
							Socket.transports = _dereq_('./transports');
							Socket.parser = _dereq_('engine.io-parser');

							/**
 * Creates transport of the given type.
 *
 * @param {String} transport name
 * @return {Transport}
 * @api private
 */

							Socket.prototype.createTransport = function(name) {
								debug('creating transport "%s"', name);
								var query = clone(this.query);

								// append engine.io protocol identifier
								query.EIO = parser.protocol;

								// transport name
								query.transport = name;

								// session id if we already have one
								if (this.id) query.sid = this.id;

								var transport = new transports[name]({
									agent: this.agent,
									hostname: this.hostname,
									port: this.port,
									secure: this.secure,
									path: this.path,
									query: query,
									forceJSONP: this.forceJSONP,
									jsonp: this.jsonp,
									forceBase64: this.forceBase64,
									enablesXDR: this.enablesXDR,
									timestampRequests: this.timestampRequests,
									timestampParam: this.timestampParam,
									policyPort: this.policyPort,
									socket: this,
									pfx: this.pfx,
									key: this.key,
									passphrase: this.passphrase,
									cert: this.cert,
									ca: this.ca,
									ciphers: this.ciphers,
									rejectUnauthorized: this.rejectUnauthorized,
								});

								return transport;
							};

							function clone(obj) {
								var o = {};
								for (var i in obj) {
									if (obj.hasOwnProperty(i)) {
										o[i] = obj[i];
									}
								}
								return o;
							}

							/**
 * Initializes transport to use and starts probe.
 *
 * @api private
 */
							Socket.prototype.open = function() {
								var transport;
								if (
									this.rememberUpgrade &&
									Socket.priorWebsocketSuccess &&
									this.transports.indexOf('websocket') != -1
								) {
									transport = 'websocket';
								} else if (0 == this.transports.length) {
									// Emit error on next tick so it can be listened to
									var self = this;
									setTimeout(function() {
										self.emit('error', 'No transports available');
									}, 0);
									return;
								} else {
									transport = this.transports[0];
								}
								this.readyState = 'opening';

								// Retry with the next transport if the transport is disabled (jsonp: false)
								var transport;
								try {
									transport = this.createTransport(transport);
								} catch (e) {
									this.transports.shift();
									this.open();
									return;
								}

								transport.open();
								this.setTransport(transport);
							};

							/**
 * Sets the current transport. Disables the existing one (if any).
 *
 * @api private
 */

							Socket.prototype.setTransport = function(transport) {
								debug('setting transport %s', transport.name);
								var self = this;

								if (this.transport) {
									debug('clearing existing transport %s', this.transport.name);
									this.transport.removeAllListeners();
								}

								// set up transport
								this.transport = transport;

								// set up transport listeners
								transport
									.on('drain', function() {
										self.onDrain();
									})
									.on('packet', function(packet) {
										self.onPacket(packet);
									})
									.on('error', function(e) {
										self.onError(e);
									})
									.on('close', function() {
										self.onClose('transport close');
									});
							};

							/**
 * Probes a transport.
 *
 * @param {String} transport name
 * @api private
 */

							Socket.prototype.probe = function(name) {
								debug('probing transport "%s"', name);
								var transport = this.createTransport(name, { probe: 1 }),
									failed = false,
									self = this;

								Socket.priorWebsocketSuccess = false;

								function onTransportOpen() {
									if (self.onlyBinaryUpgrades) {
										var upgradeLosesBinary =
											!this.supportsBinary && self.transport.supportsBinary;
										failed = failed || upgradeLosesBinary;
									}
									if (failed) return;

									debug('probe transport "%s" opened', name);
									transport.send([{ type: 'ping', data: 'probe' }]);
									transport.once('packet', function(msg) {
										if (failed) return;
										if ('pong' == msg.type && 'probe' == msg.data) {
											debug('probe transport "%s" pong', name);
											self.upgrading = true;
											self.emit('upgrading', transport);
											if (!transport) return;
											Socket.priorWebsocketSuccess =
												'websocket' == transport.name;

											debug(
												'pausing current transport "%s"',
												self.transport.name
											);
											self.transport.pause(function() {
												if (failed) return;
												if ('closed' == self.readyState) return;
												debug('changing transport and sending upgrade packet');

												cleanup();

												self.setTransport(transport);
												transport.send([{ type: 'upgrade' }]);
												self.emit('upgrade', transport);
												transport = null;
												self.upgrading = false;
												self.flush();
											});
										} else {
											debug('probe transport "%s" failed', name);
											var err = new Error('probe error');
											err.transport = transport.name;
											self.emit('upgradeError', err);
										}
									});
								}

								function freezeTransport() {
									if (failed) return;

									// Any callback called by transport should be ignored since now
									failed = true;

									cleanup();

									transport.close();
									transport = null;
								}

								//Handle any error that happens while probing
								function onerror(err) {
									var error = new Error('probe error: ' + err);
									error.transport = transport.name;

									freezeTransport();

									debug(
										'probe transport "%s" failed because of error: %s',
										name,
										err
									);

									self.emit('upgradeError', error);
								}

								function onTransportClose() {
									onerror('transport closed');
								}

								//When the socket is closed while we're probing
								function onclose() {
									onerror('socket closed');
								}

								//When the socket is upgraded while we're probing
								function onupgrade(to) {
									if (transport && to.name != transport.name) {
										debug(
											'"%s" works - aborting "%s"',
											to.name,
											transport.name
										);
										freezeTransport();
									}
								}

								//Remove all listeners on the transport and on self
								function cleanup() {
									transport.removeListener('open', onTransportOpen);
									transport.removeListener('error', onerror);
									transport.removeListener('close', onTransportClose);
									self.removeListener('close', onclose);
									self.removeListener('upgrading', onupgrade);
								}

								transport.once('open', onTransportOpen);
								transport.once('error', onerror);
								transport.once('close', onTransportClose);

								this.once('close', onclose);
								this.once('upgrading', onupgrade);

								transport.open();
							};

							/**
 * Called when connection is deemed open.
 *
 * @api public
 */

							Socket.prototype.onOpen = function() {
								debug('socket open');
								this.readyState = 'open';
								Socket.priorWebsocketSuccess =
									'websocket' == this.transport.name;
								this.emit('open');
								this.flush();

								// we check for `readyState` in case an `open`
								// listener already closed the socket
								if (
									'open' == this.readyState &&
									this.upgrade &&
									this.transport.pause
								) {
									debug('starting upgrade probes');
									for (var i = 0, l = this.upgrades.length; i < l; i++) {
										this.probe(this.upgrades[i]);
									}
								}
							};

							/**
 * Handles a packet.
 *
 * @api private
 */

							Socket.prototype.onPacket = function(packet) {
								if ('opening' == this.readyState || 'open' == this.readyState) {
									debug(
										'socket receive: type "%s", data "%s"',
										packet.type,
										packet.data
									);

									this.emit('packet', packet);

									// Socket is live - any packet counts
									this.emit('heartbeat');

									switch (packet.type) {
										case 'open':
											this.onHandshake(parsejson(packet.data));
											break;

										case 'pong':
											this.setPing();
											break;

										case 'error':
											var err = new Error('server error');
											err.code = packet.data;
											this.emit('error', err);
											break;

										case 'message':
											this.emit('data', packet.data);
											this.emit('message', packet.data);
											break;
									}
								} else {
									debug(
										'packet received with socket readyState "%s"',
										this.readyState
									);
								}
							};

							/**
 * Called upon handshake completion.
 *
 * @param {Object} handshake obj
 * @api private
 */

							Socket.prototype.onHandshake = function(data) {
								this.emit('handshake', data);
								this.id = data.sid;
								this.transport.query.sid = data.sid;
								this.upgrades = this.filterUpgrades(data.upgrades);
								this.pingInterval = data.pingInterval;
								this.pingTimeout = data.pingTimeout;
								this.onOpen();
								// In case open handler closes socket
								if ('closed' == this.readyState) return;
								this.setPing();

								// Prolong liveness of socket on heartbeat
								this.removeListener('heartbeat', this.onHeartbeat);
								this.on('heartbeat', this.onHeartbeat);
							};

							/**
 * Resets ping timeout.
 *
 * @api private
 */

							Socket.prototype.onHeartbeat = function(timeout) {
								clearTimeout(this.pingTimeoutTimer);
								var self = this;
								self.pingTimeoutTimer = setTimeout(function() {
									if ('closed' == self.readyState) return;
									self.onClose('ping timeout');
								}, timeout || self.pingInterval + self.pingTimeout);
							};

							/**
 * Pings server every `this.pingInterval` and expects response
 * within `this.pingTimeout` or closes connection.
 *
 * @api private
 */

							Socket.prototype.setPing = function() {
								var self = this;
								clearTimeout(self.pingIntervalTimer);
								self.pingIntervalTimer = setTimeout(function() {
									debug(
										'writing ping packet - expecting pong within %sms',
										self.pingTimeout
									);
									self.ping();
									self.onHeartbeat(self.pingTimeout);
								}, self.pingInterval);
							};

							/**
* Sends a ping packet.
*
* @api public
*/

							Socket.prototype.ping = function() {
								this.sendPacket('ping');
							};

							/**
 * Called on `drain` event
 *
 * @api private
 */

							Socket.prototype.onDrain = function() {
								for (var i = 0; i < this.prevBufferLen; i++) {
									if (this.callbackBuffer[i]) {
										this.callbackBuffer[i]();
									}
								}

								this.writeBuffer.splice(0, this.prevBufferLen);
								this.callbackBuffer.splice(0, this.prevBufferLen);

								// setting prevBufferLen = 0 is very important
								// for example, when upgrading, upgrade packet is sent over,
								// and a nonzero prevBufferLen could cause problems on `drain`
								this.prevBufferLen = 0;

								if (this.writeBuffer.length == 0) {
									this.emit('drain');
								} else {
									this.flush();
								}
							};

							/**
 * Flush write buffers.
 *
 * @api private
 */

							Socket.prototype.flush = function() {
								if (
									'closed' != this.readyState &&
									this.transport.writable &&
									!this.upgrading &&
									this.writeBuffer.length
								) {
									debug(
										'flushing %d packets in socket',
										this.writeBuffer.length
									);
									this.transport.send(this.writeBuffer);
									// keep track of current length of writeBuffer
									// splice writeBuffer and callbackBuffer on `drain`
									this.prevBufferLen = this.writeBuffer.length;
									this.emit('flush');
								}
							};

							/**
 * Sends a message.
 *
 * @param {String} message.
 * @param {Function} callback function.
 * @return {Socket} for chaining.
 * @api public
 */

							Socket.prototype.write = Socket.prototype.send = function(
								msg,
								fn
							) {
								this.sendPacket('message', msg, fn);
								return this;
							};

							/**
 * Sends a packet.
 *
 * @param {String} packet type.
 * @param {String} data.
 * @param {Function} callback function.
 * @api private
 */

							Socket.prototype.sendPacket = function(type, data, fn) {
								if (
									'closing' == this.readyState ||
									'closed' == this.readyState
								) {
									return;
								}

								var packet = { type: type, data: data };
								this.emit('packetCreate', packet);
								this.writeBuffer.push(packet);
								this.callbackBuffer.push(fn);
								this.flush();
							};

							/**
 * Closes the connection.
 *
 * @api private
 */

							Socket.prototype.close = function() {
								if ('opening' == this.readyState || 'open' == this.readyState) {
									this.readyState = 'closing';

									var self = this;

									function close() {
										self.onClose('forced close');
										debug('socket closing - telling transport to close');
										self.transport.close();
									}

									function cleanupAndClose() {
										self.removeListener('upgrade', cleanupAndClose);
										self.removeListener('upgradeError', cleanupAndClose);
										close();
									}

									function waitForUpgrade() {
										// wait for upgrade to finish since we can't send packets while pausing a transport
										self.once('upgrade', cleanupAndClose);
										self.once('upgradeError', cleanupAndClose);
									}

									if (this.writeBuffer.length) {
										this.once('drain', function() {
											if (this.upgrading) {
												waitForUpgrade();
											} else {
												close();
											}
										});
									} else if (this.upgrading) {
										waitForUpgrade();
									} else {
										close();
									}
								}

								return this;
							};

							/**
 * Called upon transport error
 *
 * @api private
 */

							Socket.prototype.onError = function(err) {
								debug('socket error %j', err);
								Socket.priorWebsocketSuccess = false;
								this.emit('error', err);
								this.onClose('transport error', err);
							};

							/**
 * Called upon transport close.
 *
 * @api private
 */

							Socket.prototype.onClose = function(reason, desc) {
								if (
									'opening' == this.readyState ||
									'open' == this.readyState ||
									'closing' == this.readyState
								) {
									debug('socket close with reason: "%s"', reason);
									var self = this;

									// clear timers
									clearTimeout(this.pingIntervalTimer);
									clearTimeout(this.pingTimeoutTimer);

									// clean buffers in next tick, so developers can still
									// grab the buffers on `close` event
									setTimeout(function() {
										self.writeBuffer = [];
										self.callbackBuffer = [];
										self.prevBufferLen = 0;
									}, 0);

									// stop event from firing again for transport
									this.transport.removeAllListeners('close');

									// ensure transport won't stay open
									this.transport.close();

									// ignore further transport communication
									this.transport.removeAllListeners();

									// set ready state
									this.readyState = 'closed';

									// clear session id
									this.id = null;

									// emit close event
									this.emit('close', reason, desc);
								}
							};

							/**
 * Filters upgrades, returning only those matching client transports.
 *
 * @param {Array} server upgrades
 * @api private
 *
 */

							Socket.prototype.filterUpgrades = function(upgrades) {
								var filteredUpgrades = [];
								for (var i = 0, j = upgrades.length; i < j; i++) {
									if (~index(this.transports, upgrades[i]))
										filteredUpgrades.push(upgrades[i]);
								}
								return filteredUpgrades;
							};
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{
						'./transport': 4,
						'./transports': 5,
						'component-emitter': 11,
						debug: 13,
						'engine.io-parser': 16,
						indexof: 27,
						parsejson: 28,
						parseqs: 29,
						parseuri: 30,
					},
				],
				4: [
					function(_dereq_, module, exports) {
						/**
 * Module dependencies.
 */

						var parser = _dereq_('engine.io-parser');
						var Emitter = _dereq_('component-emitter');

						/**
 * Module exports.
 */

						module.exports = Transport;

						/**
 * Transport abstract constructor.
 *
 * @param {Object} options.
 * @api private
 */

						function Transport(opts) {
							this.path = opts.path;
							this.hostname = opts.hostname;
							this.port = opts.port;
							this.secure = opts.secure;
							this.query = opts.query;
							this.timestampParam = opts.timestampParam;
							this.timestampRequests = opts.timestampRequests;
							this.readyState = '';
							this.agent = opts.agent || false;
							this.socket = opts.socket;
							this.enablesXDR = opts.enablesXDR;

							// SSL options for Node.js client
							this.pfx = opts.pfx;
							this.key = opts.key;
							this.passphrase = opts.passphrase;
							this.cert = opts.cert;
							this.ca = opts.ca;
							this.ciphers = opts.ciphers;
							this.rejectUnauthorized = opts.rejectUnauthorized;
						}

						/**
 * Mix in `Emitter`.
 */

						Emitter(Transport.prototype);

						/**
 * A counter used to prevent collisions in the timestamps used
 * for cache busting.
 */

						Transport.timestamps = 0;

						/**
 * Emits an error.
 *
 * @param {String} str
 * @return {Transport} for chaining
 * @api public
 */

						Transport.prototype.onError = function(msg, desc) {
							var err = new Error(msg);
							err.type = 'TransportError';
							err.description = desc;
							this.emit('error', err);
							return this;
						};

						/**
 * Opens the transport.
 *
 * @api public
 */

						Transport.prototype.open = function() {
							if ('closed' == this.readyState || '' == this.readyState) {
								this.readyState = 'opening';
								this.doOpen();
							}

							return this;
						};

						/**
 * Closes the transport.
 *
 * @api private
 */

						Transport.prototype.close = function() {
							if ('opening' == this.readyState || 'open' == this.readyState) {
								this.doClose();
								this.onClose();
							}

							return this;
						};

						/**
 * Sends multiple packets.
 *
 * @param {Array} packets
 * @api private
 */

						Transport.prototype.send = function(packets) {
							if ('open' == this.readyState) {
								this.write(packets);
							} else {
								throw new Error('Transport not open');
							}
						};

						/**
 * Called upon open
 *
 * @api private
 */

						Transport.prototype.onOpen = function() {
							this.readyState = 'open';
							this.writable = true;
							this.emit('open');
						};

						/**
 * Called with data.
 *
 * @param {String} data
 * @api private
 */

						Transport.prototype.onData = function(data) {
							var packet = parser.decodePacket(data, this.socket.binaryType);
							this.onPacket(packet);
						};

						/**
 * Called with a decoded packet.
 */

						Transport.prototype.onPacket = function(packet) {
							this.emit('packet', packet);
						};

						/**
 * Called upon close.
 *
 * @api private
 */

						Transport.prototype.onClose = function() {
							this.readyState = 'closed';
							this.emit('close');
						};
					},
					{ 'component-emitter': 11, 'engine.io-parser': 16 },
				],
				5: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Module dependencies
 */

							var XMLHttpRequest = _dereq_('xmlhttprequest');
							var XHR = _dereq_('./polling-xhr');
							var JSONP = _dereq_('./polling-jsonp');
							var websocket = _dereq_('./websocket');

							/**
 * Export transports.
 */

							exports.polling = polling;
							exports.websocket = websocket;

							/**
 * Polling transport polymorphic constructor.
 * Decides on xhr vs jsonp based on feature detection.
 *
 * @api private
 */

							function polling(opts) {
								var xhr;
								var xd = false;
								var xs = false;
								var jsonp = false !== opts.jsonp;

								if (global.location) {
									var isSSL = 'https:' == location.protocol;
									var port = location.port;

									// some user agents have empty `location.port`
									if (!port) {
										port = isSSL ? 443 : 80;
									}

									xd = opts.hostname != location.hostname || port != opts.port;
									xs = opts.secure != isSSL;
								}

								opts.xdomain = xd;
								opts.xscheme = xs;
								xhr = new XMLHttpRequest(opts);

								if ('open' in xhr && !opts.forceJSONP) {
									return new XHR(opts);
								} else {
									if (!jsonp) throw new Error('JSONP disabled');
									return new JSONP(opts);
								}
							}
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{
						'./polling-jsonp': 6,
						'./polling-xhr': 7,
						'./websocket': 9,
						xmlhttprequest: 10,
					},
				],
				6: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Module requirements.
 */

							var Polling = _dereq_('./polling');
							var inherit = _dereq_('component-inherit');

							/**
 * Module exports.
 */

							module.exports = JSONPPolling;

							/**
 * Cached regular expressions.
 */

							var rNewline = /\n/g;
							var rEscapedNewline = /\\n/g;

							/**
 * Global JSONP callbacks.
 */

							var callbacks;

							/**
 * Callbacks count.
 */

							var index = 0;

							/**
 * Noop.
 */

							function empty() {}

							/**
 * JSONP Polling constructor.
 *
 * @param {Object} opts.
 * @api public
 */

							function JSONPPolling(opts) {
								Polling.call(this, opts);

								this.query = this.query || {};

								// define global callbacks array if not present
								// we do this here (lazily) to avoid unneeded global pollution
								if (!callbacks) {
									// we need to consider multiple engines in the same page
									if (!global.___eio) global.___eio = [];
									callbacks = global.___eio;
								}

								// callback identifier
								this.index = callbacks.length;

								// add callback to jsonp global
								var self = this;
								callbacks.push(function(msg) {
									self.onData(msg);
								});

								// append to query string
								this.query.j = this.index;

								// prevent spurious errors from being emitted when the window is unloaded
								if (global.document && global.addEventListener) {
									global.addEventListener(
										'beforeunload',
										function() {
											if (self.script) self.script.onerror = empty;
										},
										false
									);
								}
							}

							/**
 * Inherits from Polling.
 */

							inherit(JSONPPolling, Polling);

							/*
 * JSONP only supports binary as base64 encoded strings
 */

							JSONPPolling.prototype.supportsBinary = false;

							/**
 * Closes the socket.
 *
 * @api private
 */

							JSONPPolling.prototype.doClose = function() {
								if (this.script) {
									this.script.parentNode.removeChild(this.script);
									this.script = null;
								}

								if (this.form) {
									this.form.parentNode.removeChild(this.form);
									this.form = null;
									this.iframe = null;
								}

								Polling.prototype.doClose.call(this);
							};

							/**
 * Starts a poll cycle.
 *
 * @api private
 */

							JSONPPolling.prototype.doPoll = function() {
								var self = this;
								var script = document.createElement('script');

								if (this.script) {
									this.script.parentNode.removeChild(this.script);
									this.script = null;
								}

								script.async = true;
								script.src = this.uri();
								script.onerror = function(e) {
									self.onError('jsonp poll error', e);
								};

								var insertAt = document.getElementsByTagName('script')[0];
								insertAt.parentNode.insertBefore(script, insertAt);
								this.script = script;

								var isUAgecko =
									'undefined' != typeof navigator &&
									/gecko/i.test(navigator.userAgent);

								if (isUAgecko) {
									setTimeout(function() {
										var iframe = document.createElement('iframe');
										document.body.appendChild(iframe);
										document.body.removeChild(iframe);
									}, 100);
								}
							};

							/**
 * Writes with a hidden iframe.
 *
 * @param {String} data to send
 * @param {Function} called upon flush.
 * @api private
 */

							JSONPPolling.prototype.doWrite = function(data, fn) {
								var self = this;

								if (!this.form) {
									var form = document.createElement('form');
									var area = document.createElement('textarea');
									var id = (this.iframeId = 'eio_iframe_' + this.index);
									var iframe;

									form.className = 'socketio';
									form.style.position = 'absolute';
									form.style.top = '-1000px';
									form.style.left = '-1000px';
									form.target = id;
									form.method = 'POST';
									form.setAttribute('accept-charset', 'utf-8');
									area.name = 'd';
									form.appendChild(area);
									document.body.appendChild(form);

									this.form = form;
									this.area = area;
								}

								this.form.action = this.uri();

								function complete() {
									initIframe();
									fn();
								}

								function initIframe() {
									if (self.iframe) {
										try {
											self.form.removeChild(self.iframe);
										} catch (e) {
											self.onError('jsonp polling iframe removal error', e);
										}
									}

									try {
										// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
										var html =
											'<iframe src="javascript:0" name="' +
											self.iframeId +
											'">';
										iframe = document.createElement(html);
									} catch (e) {
										iframe = document.createElement('iframe');
										iframe.name = self.iframeId;
										iframe.src = 'javascript:0';
									}

									iframe.id = self.iframeId;

									self.form.appendChild(iframe);
									self.iframe = iframe;
								}

								initIframe();

								// escape \n to prevent it from being converted into \r\n by some UAs
								// double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
								data = data.replace(rEscapedNewline, '\\\n');
								this.area.value = data.replace(rNewline, '\\n');

								try {
									this.form.submit();
								} catch (e) {}

								if (this.iframe.attachEvent) {
									this.iframe.onreadystatechange = function() {
										if (self.iframe.readyState == 'complete') {
											complete();
										}
									};
								} else {
									this.iframe.onload = complete;
								}
							};
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{ './polling': 8, 'component-inherit': 12 },
				],
				7: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Module requirements.
 */

							var XMLHttpRequest = _dereq_('xmlhttprequest');
							var Polling = _dereq_('./polling');
							var Emitter = _dereq_('component-emitter');
							var inherit = _dereq_('component-inherit');
							var debug = _dereq_('debug')('engine.io-client:polling-xhr');

							/**
 * Module exports.
 */

							module.exports = XHR;
							module.exports.Request = Request;

							/**
 * Empty function
 */

							function empty() {}

							/**
 * XHR Polling constructor.
 *
 * @param {Object} opts
 * @api public
 */

							function XHR(opts) {
								Polling.call(this, opts);

								if (global.location) {
									var isSSL = 'https:' == location.protocol;
									var port = location.port;

									// some user agents have empty `location.port`
									if (!port) {
										port = isSSL ? 443 : 80;
									}

									this.xd =
										opts.hostname != global.location.hostname ||
										port != opts.port;
									this.xs = opts.secure != isSSL;
								}
							}

							/**
 * Inherits from Polling.
 */

							inherit(XHR, Polling);

							/**
 * XHR supports binary
 */

							XHR.prototype.supportsBinary = true;

							/**
 * Creates a request.
 *
 * @param {String} method
 * @api private
 */

							XHR.prototype.request = function(opts) {
								opts = opts || {};
								opts.uri = this.uri();
								opts.xd = this.xd;
								opts.xs = this.xs;
								opts.agent = this.agent || false;
								opts.supportsBinary = this.supportsBinary;
								opts.enablesXDR = this.enablesXDR;

								// SSL options for Node.js client
								opts.pfx = this.pfx;
								opts.key = this.key;
								opts.passphrase = this.passphrase;
								opts.cert = this.cert;
								opts.ca = this.ca;
								opts.ciphers = this.ciphers;
								opts.rejectUnauthorized = this.rejectUnauthorized;

								return new Request(opts);
							};

							/**
 * Sends data.
 *
 * @param {String} data to send.
 * @param {Function} called upon flush.
 * @api private
 */

							XHR.prototype.doWrite = function(data, fn) {
								var isBinary = typeof data !== 'string' && data !== undefined;
								var req = this.request({
									method: 'POST',
									data: data,
									isBinary: isBinary,
								});
								var self = this;
								req.on('success', fn);
								req.on('error', function(err) {
									self.onError('xhr post error', err);
								});
								this.sendXhr = req;
							};

							/**
 * Starts a poll cycle.
 *
 * @api private
 */

							XHR.prototype.doPoll = function() {
								debug('xhr poll');
								var req = this.request();
								var self = this;
								req.on('data', function(data) {
									self.onData(data);
								});
								req.on('error', function(err) {
									self.onError('xhr poll error', err);
								});
								this.pollXhr = req;
							};

							/**
 * Request constructor
 *
 * @param {Object} options
 * @api public
 */

							function Request(opts) {
								this.method = opts.method || 'GET';
								this.uri = opts.uri;
								this.xd = !!opts.xd;
								this.xs = !!opts.xs;
								this.async = false !== opts.async;
								this.data = undefined != opts.data ? opts.data : null;
								this.agent = opts.agent;
								this.isBinary = opts.isBinary;
								this.supportsBinary = opts.supportsBinary;
								this.enablesXDR = opts.enablesXDR;

								// SSL options for Node.js client
								this.pfx = opts.pfx;
								this.key = opts.key;
								this.passphrase = opts.passphrase;
								this.cert = opts.cert;
								this.ca = opts.ca;
								this.ciphers = opts.ciphers;
								this.rejectUnauthorized = opts.rejectUnauthorized;

								this.create();
							}

							/**
 * Mix in `Emitter`.
 */

							Emitter(Request.prototype);

							/**
 * Creates the XHR object and sends the request.
 *
 * @api private
 */

							Request.prototype.create = function() {
								var opts = {
									agent: this.agent,
									xdomain: this.xd,
									xscheme: this.xs,
									enablesXDR: this.enablesXDR,
								};

								// SSL options for Node.js client
								opts.pfx = this.pfx;
								opts.key = this.key;
								opts.passphrase = this.passphrase;
								opts.cert = this.cert;
								opts.ca = this.ca;
								opts.ciphers = this.ciphers;
								opts.rejectUnauthorized = this.rejectUnauthorized;

								var xhr = (this.xhr = new XMLHttpRequest(opts));
								var self = this;

								try {
									debug('xhr open %s: %s', this.method, this.uri);
									xhr.open(this.method, this.uri, this.async);
									if (this.supportsBinary) {
										// This has to be done after open because Firefox is stupid
										// http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
										xhr.responseType = 'arraybuffer';
									}

									if ('POST' == this.method) {
										try {
											if (this.isBinary) {
												xhr.setRequestHeader(
													'Content-type',
													'application/octet-stream'
												);
											} else {
												xhr.setRequestHeader(
													'Content-type',
													'text/plain;charset=UTF-8'
												);
											}
										} catch (e) {}
									}

									// ie6 check
									if ('withCredentials' in xhr) {
										xhr.withCredentials = true;
									}

									if (this.hasXDR()) {
										xhr.onload = function() {
											self.onLoad();
										};
										xhr.onerror = function() {
											self.onError(xhr.responseText);
										};
									} else {
										xhr.onreadystatechange = function() {
											if (4 != xhr.readyState) return;
											if (200 == xhr.status || 1223 == xhr.status) {
												self.onLoad();
											} else {
												// make sure the `error` event handler that's user-set
												// does not throw in the same tick and gets caught here
												setTimeout(function() {
													self.onError(xhr.status);
												}, 0);
											}
										};
									}

									debug('xhr data %s', this.data);
									xhr.send(this.data);
								} catch (e) {
									// Need to defer since .create() is called directly fhrom the constructor
									// and thus the 'error' event can only be only bound *after* this exception
									// occurs.  Therefore, also, we cannot throw here at all.
									setTimeout(function() {
										self.onError(e);
									}, 0);
									return;
								}

								if (global.document) {
									this.index = Request.requestsCount++;
									Request.requests[this.index] = this;
								}
							};

							/**
 * Called upon successful response.
 *
 * @api private
 */

							Request.prototype.onSuccess = function() {
								this.emit('success');
								this.cleanup();
							};

							/**
 * Called if we have data.
 *
 * @api private
 */

							Request.prototype.onData = function(data) {
								this.emit('data', data);
								this.onSuccess();
							};

							/**
 * Called upon error.
 *
 * @api private
 */

							Request.prototype.onError = function(err) {
								this.emit('error', err);
								this.cleanup(true);
							};

							/**
 * Cleans up house.
 *
 * @api private
 */

							Request.prototype.cleanup = function(fromError) {
								if ('undefined' == typeof this.xhr || null === this.xhr) {
									return;
								}
								// xmlhttprequest
								if (this.hasXDR()) {
									this.xhr.onload = this.xhr.onerror = empty;
								} else {
									this.xhr.onreadystatechange = empty;
								}

								if (fromError) {
									try {
										this.xhr.abort();
									} catch (e) {}
								}

								if (global.document) {
									delete Request.requests[this.index];
								}

								this.xhr = null;
							};

							/**
 * Called upon load.
 *
 * @api private
 */

							Request.prototype.onLoad = function() {
								var data;
								try {
									var contentType;
									try {
										contentType = this.xhr
											.getResponseHeader('Content-Type')
											.split(';')[0];
									} catch (e) {}
									if (contentType === 'application/octet-stream') {
										data = this.xhr.response;
									} else {
										if (!this.supportsBinary) {
											data = this.xhr.responseText;
										} else {
											data = 'ok';
										}
									}
								} catch (e) {
									this.onError(e);
								}
								if (null != data) {
									this.onData(data);
								}
							};

							/**
 * Check if it has XDomainRequest.
 *
 * @api private
 */

							Request.prototype.hasXDR = function() {
								return (
									'undefined' !== typeof global.XDomainRequest &&
									!this.xs &&
									this.enablesXDR
								);
							};

							/**
 * Aborts the request.
 *
 * @api public
 */

							Request.prototype.abort = function() {
								this.cleanup();
							};

							/**
 * Aborts pending requests when unloading the window. This is needed to prevent
 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
 * emitted.
 */

							if (global.document) {
								Request.requestsCount = 0;
								Request.requests = {};
								if (global.attachEvent) {
									global.attachEvent('onunload', unloadHandler);
								} else if (global.addEventListener) {
									global.addEventListener('beforeunload', unloadHandler, false);
								}
							}

							function unloadHandler() {
								for (var i in Request.requests) {
									if (Request.requests.hasOwnProperty(i)) {
										Request.requests[i].abort();
									}
								}
							}
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{
						'./polling': 8,
						'component-emitter': 11,
						'component-inherit': 12,
						debug: 13,
						xmlhttprequest: 10,
					},
				],
				8: [
					function(_dereq_, module, exports) {
						/**
 * Module dependencies.
 */

						var Transport = _dereq_('../transport');
						var parseqs = _dereq_('parseqs');
						var parser = _dereq_('engine.io-parser');
						var inherit = _dereq_('component-inherit');
						var debug = _dereq_('debug')('engine.io-client:polling');

						/**
 * Module exports.
 */

						module.exports = Polling;

						/**
 * Is XHR2 supported?
 */

						var hasXHR2 = (function() {
							var XMLHttpRequest = _dereq_('xmlhttprequest');
							var xhr = new XMLHttpRequest({ xdomain: false });
							return null != xhr.responseType;
						})();

						/**
 * Polling interface.
 *
 * @param {Object} opts
 * @api private
 */

						function Polling(opts) {
							var forceBase64 = opts && opts.forceBase64;
							if (!hasXHR2 || forceBase64) {
								this.supportsBinary = false;
							}
							Transport.call(this, opts);
						}

						/**
 * Inherits from Transport.
 */

						inherit(Polling, Transport);

						/**
 * Transport name.
 */

						Polling.prototype.name = 'polling';

						/**
 * Opens the socket (triggers polling). We write a PING message to determine
 * when the transport is open.
 *
 * @api private
 */

						Polling.prototype.doOpen = function() {
							this.poll();
						};

						/**
 * Pauses polling.
 *
 * @param {Function} callback upon buffers are flushed and transport is paused
 * @api private
 */

						Polling.prototype.pause = function(onPause) {
							var pending = 0;
							var self = this;

							this.readyState = 'pausing';

							function pause() {
								debug('paused');
								self.readyState = 'paused';
								onPause();
							}

							if (this.polling || !this.writable) {
								var total = 0;

								if (this.polling) {
									debug('we are currently polling - waiting to pause');
									total++;
									this.once('pollComplete', function() {
										debug('pre-pause polling complete');
										--total || pause();
									});
								}

								if (!this.writable) {
									debug('we are currently writing - waiting to pause');
									total++;
									this.once('drain', function() {
										debug('pre-pause writing complete');
										--total || pause();
									});
								}
							} else {
								pause();
							}
						};

						/**
 * Starts polling cycle.
 *
 * @api public
 */

						Polling.prototype.poll = function() {
							debug('polling');
							this.polling = true;
							this.doPoll();
							this.emit('poll');
						};

						/**
 * Overloads onData to detect payloads.
 *
 * @api private
 */

						Polling.prototype.onData = function(data) {
							var self = this;
							debug('polling got data %s', data);
							var callback = function(packet, index, total) {
								// if its the first message we consider the transport open
								if ('opening' == self.readyState) {
									self.onOpen();
								}

								// if its a close packet, we close the ongoing requests
								if ('close' == packet.type) {
									self.onClose();
									return false;
								}

								// otherwise bypass onData and handle the message
								self.onPacket(packet);
							};

							// decode payload
							parser.decodePayload(data, this.socket.binaryType, callback);

							// if an event did not trigger closing
							if ('closed' != this.readyState) {
								// if we got data we're not polling
								this.polling = false;
								this.emit('pollComplete');

								if ('open' == this.readyState) {
									this.poll();
								} else {
									debug(
										'ignoring poll - transport state "%s"',
										this.readyState
									);
								}
							}
						};

						/**
 * For polling, send a close packet.
 *
 * @api private
 */

						Polling.prototype.doClose = function() {
							var self = this;

							function close() {
								debug('writing close packet');
								self.write([{ type: 'close' }]);
							}

							if ('open' == this.readyState) {
								debug('transport open - closing');
								close();
							} else {
								// in case we're trying to close while
								// handshaking is in progress (GH-164)
								debug('transport not open - deferring close');
								this.once('open', close);
							}
						};

						/**
 * Writes a packets payload.
 *
 * @param {Array} data packets
 * @param {Function} drain callback
 * @api private
 */

						Polling.prototype.write = function(packets) {
							var self = this;
							this.writable = false;
							var callbackfn = function() {
								self.writable = true;
								self.emit('drain');
							};

							var self = this;
							parser.encodePayload(packets, this.supportsBinary, function(
								data
							) {
								self.doWrite(data, callbackfn);
							});
						};

						/**
 * Generates uri for connection.
 *
 * @api private
 */

						Polling.prototype.uri = function() {
							var query = this.query || {};
							var schema = this.secure ? 'https' : 'http';
							var port = '';

							// cache busting is forced
							if (false !== this.timestampRequests) {
								query[this.timestampParam] =
									+new Date() + '-' + Transport.timestamps++;
							}

							if (!this.supportsBinary && !query.sid) {
								query.b64 = 1;
							}

							query = parseqs.encode(query);

							// avoid port if default for schema
							if (
								this.port &&
								(('https' == schema && this.port != 443) ||
									('http' == schema && this.port != 80))
							) {
								port = ':' + this.port;
							}

							// prepend ? to query
							if (query.length) {
								query = '?' + query;
							}

							return schema + '://' + this.hostname + port + this.path + query;
						};
					},
					{
						'../transport': 4,
						'component-inherit': 12,
						debug: 13,
						'engine.io-parser': 16,
						parseqs: 29,
						xmlhttprequest: 10,
					},
				],
				9: [
					function(_dereq_, module, exports) {
						/**
 * Module dependencies.
 */

						var Transport = _dereq_('../transport');
						var parser = _dereq_('engine.io-parser');
						var parseqs = _dereq_('parseqs');
						var inherit = _dereq_('component-inherit');
						var debug = _dereq_('debug')('engine.io-client:websocket');

						/**
 * `ws` exposes a WebSocket-compatible interface in
 * Node, or the `WebSocket` or `MozWebSocket` globals
 * in the browser.
 */

						var WebSocket = _dereq_('ws');

						/**
 * Module exports.
 */

						module.exports = WS;

						/**
 * WebSocket transport constructor.
 *
 * @api {Object} connection options
 * @api public
 */

						function WS(opts) {
							var forceBase64 = opts && opts.forceBase64;
							if (forceBase64) {
								this.supportsBinary = false;
							}
							Transport.call(this, opts);
						}

						/**
 * Inherits from Transport.
 */

						inherit(WS, Transport);

						/**
 * Transport name.
 *
 * @api public
 */

						WS.prototype.name = 'websocket';

						/*
 * WebSockets support binary
 */

						WS.prototype.supportsBinary = true;

						/**
 * Opens socket.
 *
 * @api private
 */

						WS.prototype.doOpen = function() {
							if (!this.check()) {
								// let probe timeout
								return;
							}

							var self = this;
							var uri = this.uri();
							var protocols = void 0;
							var opts = { agent: this.agent };

							// SSL options for Node.js client
							opts.pfx = this.pfx;
							opts.key = this.key;
							opts.passphrase = this.passphrase;
							opts.cert = this.cert;
							opts.ca = this.ca;
							opts.ciphers = this.ciphers;
							opts.rejectUnauthorized = this.rejectUnauthorized;

							this.ws = new WebSocket(uri, protocols, opts);

							if (this.ws.binaryType === undefined) {
								this.supportsBinary = false;
							}

							this.ws.binaryType = 'arraybuffer';
							this.addEventListeners();
						};

						/**
 * Adds event listeners to the socket
 *
 * @api private
 */

						WS.prototype.addEventListeners = function() {
							var self = this;

							this.ws.onopen = function() {
								self.onOpen();
							};
							this.ws.onclose = function() {
								self.onClose();
							};
							this.ws.onmessage = function(ev) {
								self.onData(ev.data);
							};
							this.ws.onerror = function(e) {
								self.onError('websocket error', e);
							};
						};

						/**
 * Override `onData` to use a timer on iOS.
 * See: https://gist.github.com/mloughran/2052006
 *
 * @api private
 */

						if (
							'undefined' != typeof navigator &&
							/iPad|iPhone|iPod/i.test(navigator.userAgent)
						) {
							WS.prototype.onData = function(data) {
								var self = this;
								setTimeout(function() {
									Transport.prototype.onData.call(self, data);
								}, 0);
							};
						}

						/**
 * Writes data to socket.
 *
 * @param {Array} array of packets.
 * @api private
 */

						WS.prototype.write = function(packets) {
							var self = this;
							this.writable = false;
							// encodePacket efficient as it uses WS framing
							// no need for encodePayload
							for (var i = 0, l = packets.length; i < l; i++) {
								parser.encodePacket(packets[i], this.supportsBinary, function(
									data
								) {
									//Sometimes the websocket has already been closed but the browser didn't
									//have a chance of informing us about it yet, in that case send will
									//throw an error
									try {
										self.ws.send(data);
									} catch (e) {
										debug('websocket closed before onclose event');
									}
								});
							}

							function ondrain() {
								self.writable = true;
								self.emit('drain');
							}
							// fake drain
							// defer to next tick to allow Socket to clear writeBuffer
							setTimeout(ondrain, 0);
						};

						/**
 * Called upon close
 *
 * @api private
 */

						WS.prototype.onClose = function() {
							Transport.prototype.onClose.call(this);
						};

						/**
 * Closes socket.
 *
 * @api private
 */

						WS.prototype.doClose = function() {
							if (typeof this.ws !== 'undefined') {
								this.ws.close();
							}
						};

						/**
 * Generates uri for connection.
 *
 * @api private
 */

						WS.prototype.uri = function() {
							var query = this.query || {};
							var schema = this.secure ? 'wss' : 'ws';
							var port = '';

							// avoid port if default for schema
							if (
								this.port &&
								(('wss' == schema && this.port != 443) ||
									('ws' == schema && this.port != 80))
							) {
								port = ':' + this.port;
							}

							// append timestamp to URI
							if (this.timestampRequests) {
								query[this.timestampParam] = +new Date();
							}

							// communicate binary support capabilities
							if (!this.supportsBinary) {
								query.b64 = 1;
							}

							query = parseqs.encode(query);

							// prepend ? to query
							if (query.length) {
								query = '?' + query;
							}

							return schema + '://' + this.hostname + port + this.path + query;
						};

						/**
 * Feature detection for WebSocket.
 *
 * @return {Boolean} whether this transport is available.
 * @api public
 */

						WS.prototype.check = function() {
							return (
								!!WebSocket &&
								!(
									'__initialize' in WebSocket && this.name === WS.prototype.name
								)
							);
						};
					},
					{
						'../transport': 4,
						'component-inherit': 12,
						debug: 13,
						'engine.io-parser': 16,
						parseqs: 29,
						ws: 31,
					},
				],
				10: [
					function(_dereq_, module, exports) {
						// browser shim for xmlhttprequest module
						var hasCORS = _dereq_('has-cors');

						module.exports = function(opts) {
							var xdomain = opts.xdomain;

							// scheme must be same when usign XDomainRequest
							// http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
							var xscheme = opts.xscheme;

							// XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
							// https://github.com/Automattic/engine.io-client/pull/217
							var enablesXDR = opts.enablesXDR;

							// XMLHttpRequest can be disabled on IE
							try {
								if (
									'undefined' != typeof XMLHttpRequest &&
									(!xdomain || hasCORS)
								) {
									return new XMLHttpRequest();
								}
							} catch (e) {}

							// Use XDomainRequest for IE8 if enablesXDR is true
							// because loading bar keeps flashing when using jsonp-polling
							// https://github.com/yujiosaka/socke.io-ie8-loading-example
							try {
								if (
									'undefined' != typeof XDomainRequest &&
									!xscheme &&
									enablesXDR
								) {
									return new XDomainRequest();
								}
							} catch (e) {}

							if (!xdomain) {
								try {
									return new window[(['Active'].concat('Object').join('X'))](
										'Microsoft.XMLHTTP'
									);
								} catch (e) {}
							}
						};
					},
					{ 'has-cors': 25 },
				],
				11: [
					function(_dereq_, module, exports) {
						/**
 * Expose `Emitter`.
 */

						module.exports = Emitter;

						/**
 * Initialize a new `Emitter`.
 *
 * @api public
 */

						function Emitter(obj) {
							if (obj) return mixin(obj);
						}

						/**
 * Mixin the emitter properties.
 *
 * @param {Object} obj
 * @return {Object}
 * @api private
 */

						function mixin(obj) {
							for (var key in Emitter.prototype) {
								obj[key] = Emitter.prototype[key];
							}
							return obj;
						}

						/**
 * Listen on the given `event` with `fn`.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

						Emitter.prototype.on = Emitter.prototype.addEventListener = function(
							event,
							fn
						) {
							this._callbacks = this._callbacks || {};
							(this._callbacks[event] = this._callbacks[event] || []).push(fn);
							return this;
						};

						/**
 * Adds an `event` listener that will be invoked a single
 * time then automatically removed.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

						Emitter.prototype.once = function(event, fn) {
							var self = this;
							this._callbacks = this._callbacks || {};

							function on() {
								self.off(event, on);
								fn.apply(this, arguments);
							}

							on.fn = fn;
							this.on(event, on);
							return this;
						};

						/**
 * Remove the given callback for `event` or all
 * registered callbacks.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

						Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(
							event,
							fn
						) {
							this._callbacks = this._callbacks || {};

							// all
							if (0 == arguments.length) {
								this._callbacks = {};
								return this;
							}

							// specific event
							var callbacks = this._callbacks[event];
							if (!callbacks) return this;

							// remove all handlers
							if (1 == arguments.length) {
								delete this._callbacks[event];
								return this;
							}

							// remove specific handler
							var cb;
							for (var i = 0; i < callbacks.length; i++) {
								cb = callbacks[i];
								if (cb === fn || cb.fn === fn) {
									callbacks.splice(i, 1);
									break;
								}
							}
							return this;
						};

						/**
 * Emit `event` with the given args.
 *
 * @param {String} event
 * @param {Mixed} ...
 * @return {Emitter}
 */

						Emitter.prototype.emit = function(event) {
							this._callbacks = this._callbacks || {};
							var args = [].slice.call(arguments, 1),
								callbacks = this._callbacks[event];

							if (callbacks) {
								callbacks = callbacks.slice(0);
								for (var i = 0, len = callbacks.length; i < len; ++i) {
									callbacks[i].apply(this, args);
								}
							}

							return this;
						};

						/**
 * Return array of callbacks for `event`.
 *
 * @param {String} event
 * @return {Array}
 * @api public
 */

						Emitter.prototype.listeners = function(event) {
							this._callbacks = this._callbacks || {};
							return this._callbacks[event] || [];
						};

						/**
 * Check if this emitter has `event` handlers.
 *
 * @param {String} event
 * @return {Boolean}
 * @api public
 */

						Emitter.prototype.hasListeners = function(event) {
							return !!this.listeners(event).length;
						};
					},
					{},
				],
				12: [
					function(_dereq_, module, exports) {
						module.exports = function(a, b) {
							var fn = function() {};
							fn.prototype = b.prototype;
							a.prototype = new fn();
							a.prototype.constructor = a;
						};
					},
					{},
				],
				13: [
					function(_dereq_, module, exports) {
						/**
 * This is the web browser implementation of `debug()`.
 *
 * Expose `debug()` as the module.
 */

						exports = module.exports = _dereq_('./debug');
						exports.log = log;
						exports.formatArgs = formatArgs;
						exports.save = save;
						exports.load = load;
						exports.useColors = useColors;

						/**
 * Colors.
 */

						exports.colors = [
							'lightseagreen',
							'forestgreen',
							'goldenrod',
							'dodgerblue',
							'darkorchid',
							'crimson',
						];

						/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

						function useColors() {
							// is webkit? http://stackoverflow.com/a/16459606/376773
							return (
								'WebkitAppearance' in document.documentElement.style ||
								// is firebug? http://stackoverflow.com/a/398120/376773
								(window.console &&
									(console.firebug || (console.exception && console.table))) ||
								// is firefox >= v31?
								// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
								(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) &&
									parseInt(RegExp.$1, 10) >= 31)
							);
						}

						/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

						exports.formatters.j = function(v) {
							return JSON.stringify(v);
						};

						/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

						function formatArgs() {
							var args = arguments;
							var useColors = this.useColors;

							args[0] =
								(useColors ? '%c' : '') +
								this.namespace +
								(useColors ? ' %c' : ' ') +
								args[0] +
								(useColors ? '%c ' : ' ') +
								'+' +
								exports.humanize(this.diff);

							if (!useColors) return args;

							var c = 'color: ' + this.color;
							args = [args[0], c, 'color: inherit'].concat(
								Array.prototype.slice.call(args, 1)
							);

							// the final "%c" is somewhat tricky, because there could be other
							// arguments passed either before or after the %c, so we need to
							// figure out the correct index to insert the CSS into
							var index = 0;
							var lastC = 0;
							args[0].replace(/%[a-z%]/g, function(match) {
								if ('%%' === match) return;
								index++;
								if ('%c' === match) {
									// we only are interested in the *last* %c
									// (the user may have provided their own)
									lastC = index;
								}
							});

							args.splice(lastC, 0, c);
							return args;
						}

						/**
 * Invokes `console.log()` when available.
 * No-op when `console.log` is not a "function".
 *
 * @api public
 */

						function log() {
							// This hackery is required for IE8,
							// where the `console.log` function doesn't have 'apply'
							return (
								'object' == typeof console &&
								'function' == typeof console.log &&
								Function.prototype.apply.call(console.log, console, arguments)
							);
						}

						/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */

						function save(namespaces) {
							try {
								if (null == namespaces) {
									localStorage.removeItem('debug');
								} else {
									localStorage.debug = namespaces;
								}
							} catch (e) {}
						}

						/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */

						function load() {
							var r;
							try {
								r = localStorage.debug;
							} catch (e) {}
							return r;
						}

						/**
 * Enable namespaces listed in `localStorage.debug` initially.
 */

						exports.enable(load());
					},
					{ './debug': 14 },
				],
				14: [
					function(_dereq_, module, exports) {
						/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 *
 * Expose `debug()` as the module.
 */

						exports = module.exports = debug;
						exports.coerce = coerce;
						exports.disable = disable;
						exports.enable = enable;
						exports.enabled = enabled;
						exports.humanize = _dereq_('ms');

						/**
 * The currently active debug mode names, and names to skip.
 */

						exports.names = [];
						exports.skips = [];

						/**
 * Map of special "%n" handling functions, for the debug "format" argument.
 *
 * Valid key names are a single, lowercased letter, i.e. "n".
 */

						exports.formatters = {};

						/**
 * Previously assigned color.
 */

						var prevColor = 0;

						/**
 * Previous log timestamp.
 */

						var prevTime;

						/**
 * Select a color.
 *
 * @return {Number}
 * @api private
 */

						function selectColor() {
							return exports.colors[prevColor++ % exports.colors.length];
						}

						/**
 * Create a debugger with the given `namespace`.
 *
 * @param {String} namespace
 * @return {Function}
 * @api public
 */

						function debug(namespace) {
							// define the `disabled` version
							function disabled() {}
							disabled.enabled = false;

							// define the `enabled` version
							function enabled() {
								var self = enabled;

								// set `diff` timestamp
								var curr = +new Date();
								var ms = curr - (prevTime || curr);
								self.diff = ms;
								self.prev = prevTime;
								self.curr = curr;
								prevTime = curr;

								// add the `color` if not set
								if (null == self.useColors)
									self.useColors = exports.useColors();
								if (null == self.color && self.useColors)
									self.color = selectColor();

								var args = Array.prototype.slice.call(arguments);

								args[0] = exports.coerce(args[0]);

								if ('string' !== typeof args[0]) {
									// anything else let's inspect with %o
									args = ['%o'].concat(args);
								}

								// apply any `formatters` transformations
								var index = 0;
								args[0] = args[0].replace(/%([a-z%])/g, function(
									match,
									format
								) {
									// if we encounter an escaped % then don't increase the array index
									if (match === '%%') return match;
									index++;
									var formatter = exports.formatters[format];
									if ('function' === typeof formatter) {
										var val = args[index];
										match = formatter.call(self, val);

										// now we need to remove `args[index]` since it's inlined in the `format`
										args.splice(index, 1);
										index--;
									}
									return match;
								});

								if ('function' === typeof exports.formatArgs) {
									args = exports.formatArgs.apply(self, args);
								}
								var logFn =
									enabled.log || exports.log || console.log.bind(console);
								logFn.apply(self, args);
							}
							enabled.enabled = true;

							var fn = exports.enabled(namespace) ? enabled : disabled;

							fn.namespace = namespace;

							return fn;
						}

						/**
 * Enables a debug mode by namespaces. This can include modes
 * separated by a colon and wildcards.
 *
 * @param {String} namespaces
 * @api public
 */

						function enable(namespaces) {
							exports.save(namespaces);

							var split = (namespaces || '').split(/[\s,]+/);
							var len = split.length;

							for (var i = 0; i < len; i++) {
								if (!split[i]) continue; // ignore empty strings
								namespaces = split[i].replace(/\*/g, '.*?');
								if (namespaces[0] === '-') {
									exports.skips.push(
										new RegExp('^' + namespaces.substr(1) + '$')
									);
								} else {
									exports.names.push(new RegExp('^' + namespaces + '$'));
								}
							}
						}

						/**
 * Disable debug output.
 *
 * @api public
 */

						function disable() {
							exports.enable('');
						}

						/**
 * Returns true if the given mode name is enabled, false otherwise.
 *
 * @param {String} name
 * @return {Boolean}
 * @api public
 */

						function enabled(name) {
							var i, len;
							for (i = 0, len = exports.skips.length; i < len; i++) {
								if (exports.skips[i].test(name)) {
									return false;
								}
							}
							for (i = 0, len = exports.names.length; i < len; i++) {
								if (exports.names[i].test(name)) {
									return true;
								}
							}
							return false;
						}

						/**
 * Coerce `val`.
 *
 * @param {Mixed} val
 * @return {Mixed}
 * @api private
 */

						function coerce(val) {
							if (val instanceof Error) return val.stack || val.message;
							return val;
						}
					},
					{ ms: 15 },
				],
				15: [
					function(_dereq_, module, exports) {
						/**
 * Helpers.
 */

						var s = 1000;
						var m = s * 60;
						var h = m * 60;
						var d = h * 24;
						var y = d * 365.25;

						/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

						module.exports = function(val, options) {
							options = options || {};
							if ('string' == typeof val) return parse(val);
							return options.long ? long(val) : short(val);
						};

						/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

						function parse(str) {
							var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(
								str
							);
							if (!match) return;
							var n = parseFloat(match[1]);
							var type = (match[2] || 'ms').toLowerCase();
							switch (type) {
								case 'years':
								case 'year':
								case 'y':
									return n * y;
								case 'days':
								case 'day':
								case 'd':
									return n * d;
								case 'hours':
								case 'hour':
								case 'h':
									return n * h;
								case 'minutes':
								case 'minute':
								case 'm':
									return n * m;
								case 'seconds':
								case 'second':
								case 's':
									return n * s;
								case 'ms':
									return n;
							}
						}

						/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

						function short(ms) {
							if (ms >= d) return Math.round(ms / d) + 'd';
							if (ms >= h) return Math.round(ms / h) + 'h';
							if (ms >= m) return Math.round(ms / m) + 'm';
							if (ms >= s) return Math.round(ms / s) + 's';
							return ms + 'ms';
						}

						/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

						function long(ms) {
							return (
								plural(ms, d, 'day') ||
								plural(ms, h, 'hour') ||
								plural(ms, m, 'minute') ||
								plural(ms, s, 'second') ||
								ms + ' ms'
							);
						}

						/**
 * Pluralization helper.
 */

						function plural(ms, n, name) {
							if (ms < n) return;
							if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
							return Math.ceil(ms / n) + ' ' + name + 's';
						}
					},
					{},
				],
				16: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Module dependencies.
 */

							var keys = _dereq_('./keys');
							var hasBinary = _dereq_('has-binary');
							var sliceBuffer = _dereq_('arraybuffer.slice');
							var base64encoder = _dereq_('base64-arraybuffer');
							var after = _dereq_('after');
							var utf8 = _dereq_('utf8');

							/**
 * Check if we are running an android browser. That requires us to use
 * ArrayBuffer with polling transports...
 *
 * http://ghinda.net/jpeg-blob-ajax-android/
 */

							var isAndroid = navigator.userAgent.match(/Android/i);

							/**
 * Check if we are running in PhantomJS.
 * Uploading a Blob with PhantomJS does not work correctly, as reported here:
 * https://github.com/ariya/phantomjs/issues/11395
 * @type boolean
 */
							var isPhantomJS = /PhantomJS/i.test(navigator.userAgent);

							/**
 * When true, avoids using Blobs to encode payloads.
 * @type boolean
 */
							var dontSendBlobs = isAndroid || isPhantomJS;

							/**
 * Current protocol version.
 */

							exports.protocol = 3;

							/**
 * Packet types.
 */

							var packets = (exports.packets = {
								open: 0, // non-ws
								close: 1, // non-ws
								ping: 2,
								pong: 3,
								message: 4,
								upgrade: 5,
								noop: 6,
							});

							var packetslist = keys(packets);

							/**
 * Premade error packet.
 */

							var err = { type: 'error', data: 'parser error' };

							/**
 * Create a blob api even for blob builder when vendor prefixes exist
 */

							var Blob = _dereq_('blob');

							/**
 * Encodes a packet.
 *
 *     <packet type id> [ <data> ]
 *
 * Example:
 *
 *     5hello world
 *     3
 *     4
 *
 * Binary is encoded in an identical principle
 *
 * @api private
 */

							exports.encodePacket = function(
								packet,
								supportsBinary,
								utf8encode,
								callback
							) {
								if ('function' == typeof supportsBinary) {
									callback = supportsBinary;
									supportsBinary = false;
								}

								if ('function' == typeof utf8encode) {
									callback = utf8encode;
									utf8encode = null;
								}

								var data = packet.data === undefined
									? undefined
									: packet.data.buffer || packet.data;

								if (global.ArrayBuffer && data instanceof ArrayBuffer) {
									return encodeArrayBuffer(packet, supportsBinary, callback);
								} else if (Blob && data instanceof global.Blob) {
									return encodeBlob(packet, supportsBinary, callback);
								}

								// might be an object with { base64: true, data: dataAsBase64String }
								if (data && data.base64) {
									return encodeBase64Object(packet, callback);
								}

								// Sending data as a utf-8 string
								var encoded = packets[packet.type];

								// data fragment is optional
								if (undefined !== packet.data) {
									encoded += utf8encode
										? utf8.encode(String(packet.data))
										: String(packet.data);
								}

								return callback('' + encoded);
							};

							function encodeBase64Object(packet, callback) {
								// packet data is an object { base64: true, data: dataAsBase64String }
								var message =
									'b' + exports.packets[packet.type] + packet.data.data;
								return callback(message);
							}

							/**
 * Encode packet helpers for binary types
 */

							function encodeArrayBuffer(packet, supportsBinary, callback) {
								if (!supportsBinary) {
									return exports.encodeBase64Packet(packet, callback);
								}

								var data = packet.data;
								var contentArray = new Uint8Array(data);
								var resultBuffer = new Uint8Array(1 + data.byteLength);

								resultBuffer[0] = packets[packet.type];
								for (var i = 0; i < contentArray.length; i++) {
									resultBuffer[i + 1] = contentArray[i];
								}

								return callback(resultBuffer.buffer);
							}

							function encodeBlobAsArrayBuffer(
								packet,
								supportsBinary,
								callback
							) {
								if (!supportsBinary) {
									return exports.encodeBase64Packet(packet, callback);
								}

								var fr = new FileReader();
								fr.onload = function() {
									packet.data = fr.result;
									exports.encodePacket(packet, supportsBinary, true, callback);
								};
								return fr.readAsArrayBuffer(packet.data);
							}

							function encodeBlob(packet, supportsBinary, callback) {
								if (!supportsBinary) {
									return exports.encodeBase64Packet(packet, callback);
								}

								if (dontSendBlobs) {
									return encodeBlobAsArrayBuffer(
										packet,
										supportsBinary,
										callback
									);
								}

								var length = new Uint8Array(1);
								length[0] = packets[packet.type];
								var blob = new Blob([length.buffer, packet.data]);

								return callback(blob);
							}

							/**
 * Encodes a packet with binary data in a base64 string
 *
 * @param {Object} packet, has `type` and `data`
 * @return {String} base64 encoded message
 */

							exports.encodeBase64Packet = function(packet, callback) {
								var message = 'b' + exports.packets[packet.type];
								if (Blob && packet.data instanceof Blob) {
									var fr = new FileReader();
									fr.onload = function() {
										var b64 = fr.result.split(',')[1];
										callback(message + b64);
									};
									return fr.readAsDataURL(packet.data);
								}

								var b64data;
								try {
									b64data = String.fromCharCode.apply(
										null,
										new Uint8Array(packet.data)
									);
								} catch (e) {
									// iPhone Safari doesn't let you apply with typed arrays
									var typed = new Uint8Array(packet.data);
									var basic = new Array(typed.length);
									for (var i = 0; i < typed.length; i++) {
										basic[i] = typed[i];
									}
									b64data = String.fromCharCode.apply(null, basic);
								}
								message += global.btoa(b64data);
								return callback(message);
							};

							/**
 * Decodes a packet. Changes format to Blob if requested.
 *
 * @return {Object} with `type` and `data` (if any)
 * @api private
 */

							exports.decodePacket = function(data, binaryType, utf8decode) {
								// String data
								if (typeof data == 'string' || data === undefined) {
									if (data.charAt(0) == 'b') {
										return exports.decodeBase64Packet(
											data.substr(1),
											binaryType
										);
									}

									if (utf8decode) {
										try {
											data = utf8.decode(data);
										} catch (e) {
											return err;
										}
									}
									var type = data.charAt(0);

									if (Number(type) != type || !packetslist[type]) {
										return err;
									}

									if (data.length > 1) {
										return { type: packetslist[type], data: data.substring(1) };
									} else {
										return { type: packetslist[type] };
									}
								}

								var asArray = new Uint8Array(data);
								var type = asArray[0];
								var rest = sliceBuffer(data, 1);
								if (Blob && binaryType === 'blob') {
									rest = new Blob([rest]);
								}
								return { type: packetslist[type], data: rest };
							};

							/**
 * Decodes a packet encoded in a base64 string
 *
 * @param {String} base64 encoded message
 * @return {Object} with `type` and `data` (if any)
 */

							exports.decodeBase64Packet = function(msg, binaryType) {
								var type = packetslist[msg.charAt(0)];
								if (!global.ArrayBuffer) {
									return {
										type: type,
										data: { base64: true, data: msg.substr(1) },
									};
								}

								var data = base64encoder.decode(msg.substr(1));

								if (binaryType === 'blob' && Blob) {
									data = new Blob([data]);
								}

								return { type: type, data: data };
							};

							/**
 * Encodes multiple messages (payload).
 *
 *     <length>:data
 *
 * Example:
 *
 *     11:hello world2:hi
 *
 * If any contents are binary, they will be encoded as base64 strings. Base64
 * encoded strings are marked with a b before the length specifier
 *
 * @param {Array} packets
 * @api private
 */

							exports.encodePayload = function(
								packets,
								supportsBinary,
								callback
							) {
								if (typeof supportsBinary == 'function') {
									callback = supportsBinary;
									supportsBinary = null;
								}

								var isBinary = hasBinary(packets);

								if (supportsBinary && isBinary) {
									if (Blob && !dontSendBlobs) {
										return exports.encodePayloadAsBlob(packets, callback);
									}

									return exports.encodePayloadAsArrayBuffer(packets, callback);
								}

								if (!packets.length) {
									return callback('0:');
								}

								function setLengthHeader(message) {
									return message.length + ':' + message;
								}

								function encodeOne(packet, doneCallback) {
									exports.encodePacket(
										packet,
										!isBinary ? false : supportsBinary,
										true,
										function(message) {
											doneCallback(null, setLengthHeader(message));
										}
									);
								}

								map(packets, encodeOne, function(err, results) {
									return callback(results.join(''));
								});
							};

							/**
 * Async array map using after
 */

							function map(ary, each, done) {
								var result = new Array(ary.length);
								var next = after(ary.length, done);

								var eachWithIndex = function(i, el, cb) {
									each(el, function(error, msg) {
										result[i] = msg;
										cb(error, result);
									});
								};

								for (var i = 0; i < ary.length; i++) {
									eachWithIndex(i, ary[i], next);
								}
							}

							/*
 * Decodes data when a payload is maybe expected. Possible binary contents are
 * decoded from their base64 representation
 *
 * @param {String} data, callback method
 * @api public
 */

							exports.decodePayload = function(data, binaryType, callback) {
								if (typeof data != 'string') {
									return exports.decodePayloadAsBinary(
										data,
										binaryType,
										callback
									);
								}

								if (typeof binaryType === 'function') {
									callback = binaryType;
									binaryType = null;
								}

								var packet;
								if (data == '') {
									// parser error - ignoring payload
									return callback(err, 0, 1);
								}

								var length = '',
									n,
									msg;

								for (var i = 0, l = data.length; i < l; i++) {
									var chr = data.charAt(i);

									if (':' != chr) {
										length += chr;
									} else {
										if ('' == length || length != (n = Number(length))) {
											// parser error - ignoring payload
											return callback(err, 0, 1);
										}

										msg = data.substr(i + 1, n);

										if (length != msg.length) {
											// parser error - ignoring payload
											return callback(err, 0, 1);
										}

										if (msg.length) {
											packet = exports.decodePacket(msg, binaryType, true);

											if (err.type == packet.type && err.data == packet.data) {
												// parser error in individual packet - ignoring payload
												return callback(err, 0, 1);
											}

											var ret = callback(packet, i + n, l);
											if (false === ret) return;
										}

										// advance cursor
										i += n;
										length = '';
									}
								}

								if (length != '') {
									// parser error - ignoring payload
									return callback(err, 0, 1);
								}
							};

							/**
 * Encodes multiple messages (payload) as binary.
 *
 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
 * 255><data>
 *
 * Example:
 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
 *
 * @param {Array} packets
 * @return {ArrayBuffer} encoded payload
 * @api private
 */

							exports.encodePayloadAsArrayBuffer = function(packets, callback) {
								if (!packets.length) {
									return callback(new ArrayBuffer(0));
								}

								function encodeOne(packet, doneCallback) {
									exports.encodePacket(packet, true, true, function(data) {
										return doneCallback(null, data);
									});
								}

								map(packets, encodeOne, function(err, encodedPackets) {
									var totalLength = encodedPackets.reduce(function(acc, p) {
										var len;
										if (typeof p === 'string') {
											len = p.length;
										} else {
											len = p.byteLength;
										}
										return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
									}, 0);

									var resultArray = new Uint8Array(totalLength);

									var bufferIndex = 0;
									encodedPackets.forEach(function(p) {
										var isString = typeof p === 'string';
										var ab = p;
										if (isString) {
											var view = new Uint8Array(p.length);
											for (var i = 0; i < p.length; i++) {
												view[i] = p.charCodeAt(i);
											}
											ab = view.buffer;
										}

										if (isString) {
											// not true binary
											resultArray[bufferIndex++] = 0;
										} else {
											// true binary
											resultArray[bufferIndex++] = 1;
										}

										var lenStr = ab.byteLength.toString();
										for (var i = 0; i < lenStr.length; i++) {
											resultArray[bufferIndex++] = parseInt(lenStr[i]);
										}
										resultArray[bufferIndex++] = 255;

										var view = new Uint8Array(ab);
										for (var i = 0; i < view.length; i++) {
											resultArray[bufferIndex++] = view[i];
										}
									});

									return callback(resultArray.buffer);
								});
							};

							/**
 * Encode as Blob
 */

							exports.encodePayloadAsBlob = function(packets, callback) {
								function encodeOne(packet, doneCallback) {
									exports.encodePacket(packet, true, true, function(encoded) {
										var binaryIdentifier = new Uint8Array(1);
										binaryIdentifier[0] = 1;
										if (typeof encoded === 'string') {
											var view = new Uint8Array(encoded.length);
											for (var i = 0; i < encoded.length; i++) {
												view[i] = encoded.charCodeAt(i);
											}
											encoded = view.buffer;
											binaryIdentifier[0] = 0;
										}

										var len = encoded instanceof ArrayBuffer
											? encoded.byteLength
											: encoded.size;

										var lenStr = len.toString();
										var lengthAry = new Uint8Array(lenStr.length + 1);
										for (var i = 0; i < lenStr.length; i++) {
											lengthAry[i] = parseInt(lenStr[i]);
										}
										lengthAry[lenStr.length] = 255;

										if (Blob) {
											var blob = new Blob([
												binaryIdentifier.buffer,
												lengthAry.buffer,
												encoded,
											]);
											doneCallback(null, blob);
										}
									});
								}

								map(packets, encodeOne, function(err, results) {
									return callback(new Blob(results));
								});
							};

							/*
 * Decodes data when a payload is maybe expected. Strings are decoded by
 * interpreting each byte as a key code for entries marked to start with 0. See
 * description of encodePayloadAsBinary
 *
 * @param {ArrayBuffer} data, callback method
 * @api public
 */

							exports.decodePayloadAsBinary = function(
								data,
								binaryType,
								callback
							) {
								if (typeof binaryType === 'function') {
									callback = binaryType;
									binaryType = null;
								}

								var bufferTail = data;
								var buffers = [];

								var numberTooLong = false;
								while (bufferTail.byteLength > 0) {
									var tailArray = new Uint8Array(bufferTail);
									var isString = tailArray[0] === 0;
									var msgLength = '';

									for (var i = 1; ; i++) {
										if (tailArray[i] == 255) break;

										if (msgLength.length > 310) {
											numberTooLong = true;
											break;
										}

										msgLength += tailArray[i];
									}

									if (numberTooLong) return callback(err, 0, 1);

									bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
									msgLength = parseInt(msgLength);

									var msg = sliceBuffer(bufferTail, 0, msgLength);
									if (isString) {
										try {
											msg = String.fromCharCode.apply(
												null,
												new Uint8Array(msg)
											);
										} catch (e) {
											// iPhone Safari doesn't let you apply to typed arrays
											var typed = new Uint8Array(msg);
											msg = '';
											for (var i = 0; i < typed.length; i++) {
												msg += String.fromCharCode(typed[i]);
											}
										}
									}

									buffers.push(msg);
									bufferTail = sliceBuffer(bufferTail, msgLength);
								}

								var total = buffers.length;
								buffers.forEach(function(buffer, i) {
									callback(
										exports.decodePacket(buffer, binaryType, true),
										i,
										total
									);
								});
							};
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{
						'./keys': 17,
						after: 18,
						'arraybuffer.slice': 19,
						'base64-arraybuffer': 20,
						blob: 21,
						'has-binary': 22,
						utf8: 24,
					},
				],
				17: [
					function(_dereq_, module, exports) {
						/**
 * Gets the keys for an object.
 *
 * @return {Array} keys
 * @api private
 */

						module.exports =
							Object.keys ||
							function keys(obj) {
								var arr = [];
								var has = Object.prototype.hasOwnProperty;

								for (var i in obj) {
									if (has.call(obj, i)) {
										arr.push(i);
									}
								}
								return arr;
							};
					},
					{},
				],
				18: [
					function(_dereq_, module, exports) {
						module.exports = after;

						function after(count, callback, err_cb) {
							var bail = false;
							err_cb = err_cb || noop;
							proxy.count = count;

							return count === 0 ? callback() : proxy;

							function proxy(err, result) {
								if (proxy.count <= 0) {
									throw new Error('after called too many times');
								}
								--proxy.count;

								// after first error, rest are passed to err_cb
								if (err) {
									bail = true;
									callback(err);
									// future error callbacks will go to error handler
									callback = err_cb;
								} else if (proxy.count === 0 && !bail) {
									callback(null, result);
								}
							}
						}

						function noop() {}
					},
					{},
				],
				19: [
					function(_dereq_, module, exports) {
						/**
 * An abstraction for slicing an arraybuffer even when
 * ArrayBuffer.prototype.slice is not supported
 *
 * @api public
 */

						module.exports = function(arraybuffer, start, end) {
							var bytes = arraybuffer.byteLength;
							start = start || 0;
							end = end || bytes;

							if (arraybuffer.slice) {
								return arraybuffer.slice(start, end);
							}

							if (start < 0) {
								start += bytes;
							}
							if (end < 0) {
								end += bytes;
							}
							if (end > bytes) {
								end = bytes;
							}

							if (start >= bytes || start >= end || bytes === 0) {
								return new ArrayBuffer(0);
							}

							var abv = new Uint8Array(arraybuffer);
							var result = new Uint8Array(end - start);
							for (var i = start, ii = 0; i < end; i++, ii++) {
								result[ii] = abv[i];
							}
							return result.buffer;
						};
					},
					{},
				],
				20: [
					function(_dereq_, module, exports) {
						/*
 * base64-arraybuffer
 * https://github.com/niklasvh/base64-arraybuffer
 *
 * Copyright (c) 2012 Niklas von Hertzen
 * Licensed under the MIT license.
 */
						(function(chars) {
							'use strict';

							exports.encode = function(arraybuffer) {
								var bytes = new Uint8Array(arraybuffer),
									i,
									len = bytes.length,
									base64 = '';

								for (i = 0; i < len; i += 3) {
									base64 += chars[bytes[i] >> 2];
									base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
									base64 +=
										chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
									base64 += chars[bytes[i + 2] & 63];
								}

								if (len % 3 === 2) {
									base64 = base64.substring(0, base64.length - 1) + '=';
								} else if (len % 3 === 1) {
									base64 = base64.substring(0, base64.length - 2) + '==';
								}

								return base64;
							};

							exports.decode = function(base64) {
								var bufferLength = base64.length * 0.75,
									len = base64.length,
									i,
									p = 0,
									encoded1,
									encoded2,
									encoded3,
									encoded4;

								if (base64[base64.length - 1] === '=') {
									bufferLength--;
									if (base64[base64.length - 2] === '=') {
										bufferLength--;
									}
								}

								var arraybuffer = new ArrayBuffer(bufferLength),
									bytes = new Uint8Array(arraybuffer);

								for (i = 0; i < len; i += 4) {
									encoded1 = chars.indexOf(base64[i]);
									encoded2 = chars.indexOf(base64[i + 1]);
									encoded3 = chars.indexOf(base64[i + 2]);
									encoded4 = chars.indexOf(base64[i + 3]);

									bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
									bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
									bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
								}

								return arraybuffer;
							};
						})(
							'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
						);
					},
					{},
				],
				21: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * Create a blob builder even when vendor prefixes exist
 */

							var BlobBuilder =
								global.BlobBuilder ||
								global.WebKitBlobBuilder ||
								global.MSBlobBuilder ||
								global.MozBlobBuilder;

							/**
 * Check if Blob constructor is supported
 */

							var blobSupported = (function() {
								try {
									var b = new Blob(['hi']);
									return b.size == 2;
								} catch (e) {
									return false;
								}
							})();

							/**
 * Check if BlobBuilder is supported
 */

							var blobBuilderSupported =
								BlobBuilder &&
								BlobBuilder.prototype.append &&
								BlobBuilder.prototype.getBlob;

							function BlobBuilderConstructor(ary, options) {
								options = options || {};

								var bb = new BlobBuilder();
								for (var i = 0; i < ary.length; i++) {
									bb.append(ary[i]);
								}
								return options.type ? bb.getBlob(options.type) : bb.getBlob();
							}

							module.exports = (function() {
								if (blobSupported) {
									return global.Blob;
								} else if (blobBuilderSupported) {
									return BlobBuilderConstructor;
								} else {
									return undefined;
								}
							})();
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{},
				],
				22: [
					function(_dereq_, module, exports) {
						(function(global) {
							/*
 * Module requirements.
 */

							var isArray = _dereq_('isarray');

							/**
 * Module exports.
 */

							module.exports = hasBinary;

							/**
 * Checks for binary data.
 *
 * Right now only Buffer and ArrayBuffer are supported..
 *
 * @param {Object} anything
 * @api public
 */

							function hasBinary(data) {
								function _hasBinary(obj) {
									if (!obj) return false;

									if (
										(global.Buffer && global.Buffer.isBuffer(obj)) ||
										(global.ArrayBuffer && obj instanceof ArrayBuffer) ||
										(global.Blob && obj instanceof Blob) ||
										(global.File && obj instanceof File)
									) {
										return true;
									}

									if (isArray(obj)) {
										for (var i = 0; i < obj.length; i++) {
											if (_hasBinary(obj[i])) {
												return true;
											}
										}
									} else if (obj && 'object' == typeof obj) {
										if (obj.toJSON) {
											obj = obj.toJSON();
										}

										for (var key in obj) {
											if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) {
												return true;
											}
										}
									}

									return false;
								}

								return _hasBinary(data);
							}
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{ isarray: 23 },
				],
				23: [
					function(_dereq_, module, exports) {
						module.exports =
							Array.isArray ||
							function(arr) {
								return Object.prototype.toString.call(arr) == '[object Array]';
							};
					},
					{},
				],
				24: [
					function(_dereq_, module, exports) {
						(function(global) {
							/*! http://mths.be/utf8js v2.0.0 by @mathias */
							(function(root) {
								// Detect free variables `exports`
								var freeExports = typeof exports == 'object' && exports;

								// Detect free variable `module`
								var freeModule =
									typeof module == 'object' &&
									module &&
									module.exports == freeExports &&
									module;

								// Detect free variable `global`, from Node.js or Browserified code,
								// and use it as `root`
								var freeGlobal = typeof global == 'object' && global;
								if (
									freeGlobal.global === freeGlobal ||
									freeGlobal.window === freeGlobal
								) {
									root = freeGlobal;
								}

								/*--------------------------------------------------------------------------*/

								var stringFromCharCode = String.fromCharCode;

								// Taken from http://mths.be/punycode
								function ucs2decode(string) {
									var output = [];
									var counter = 0;
									var length = string.length;
									var value;
									var extra;
									while (counter < length) {
										value = string.charCodeAt(counter++);
										if (
											value >= 0xd800 &&
											value <= 0xdbff &&
											counter < length
										) {
											// high surrogate, and there is a next character
											extra = string.charCodeAt(counter++);
											if ((extra & 0xfc00) == 0xdc00) {
												// low surrogate
												output.push(
													((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000
												);
											} else {
												// unmatched surrogate; only append this code unit, in case the next
												// code unit is the high surrogate of a surrogate pair
												output.push(value);
												counter--;
											}
										} else {
											output.push(value);
										}
									}
									return output;
								}

								// Taken from http://mths.be/punycode
								function ucs2encode(array) {
									var length = array.length;
									var index = -1;
									var value;
									var output = '';
									while (++index < length) {
										value = array[index];
										if (value > 0xffff) {
											value -= 0x10000;
											output += stringFromCharCode(
												((value >>> 10) & 0x3ff) | 0xd800
											);
											value = 0xdc00 | (value & 0x3ff);
										}
										output += stringFromCharCode(value);
									}
									return output;
								}

								/*--------------------------------------------------------------------------*/

								function createByte(codePoint, shift) {
									return stringFromCharCode(
										((codePoint >> shift) & 0x3f) | 0x80
									);
								}

								function encodeCodePoint(codePoint) {
									if ((codePoint & 0xffffff80) == 0) {
										// 1-byte sequence
										return stringFromCharCode(codePoint);
									}
									var symbol = '';
									if ((codePoint & 0xfffff800) == 0) {
										// 2-byte sequence
										symbol = stringFromCharCode(
											((codePoint >> 6) & 0x1f) | 0xc0
										);
									} else if ((codePoint & 0xffff0000) == 0) {
										// 3-byte sequence
										symbol = stringFromCharCode(
											((codePoint >> 12) & 0x0f) | 0xe0
										);
										symbol += createByte(codePoint, 6);
									} else if ((codePoint & 0xffe00000) == 0) {
										// 4-byte sequence
										symbol = stringFromCharCode(
											((codePoint >> 18) & 0x07) | 0xf0
										);
										symbol += createByte(codePoint, 12);
										symbol += createByte(codePoint, 6);
									}
									symbol += stringFromCharCode((codePoint & 0x3f) | 0x80);
									return symbol;
								}

								function utf8encode(string) {
									var codePoints = ucs2decode(string);

									// console.log(JSON.stringify(codePoints.map(function(x) {
									// 	return 'U+' + x.toString(16).toUpperCase();
									// })));

									var length = codePoints.length;
									var index = -1;
									var codePoint;
									var byteString = '';
									while (++index < length) {
										codePoint = codePoints[index];
										byteString += encodeCodePoint(codePoint);
									}
									return byteString;
								}

								/*--------------------------------------------------------------------------*/

								function readContinuationByte() {
									if (byteIndex >= byteCount) {
										throw Error('Invalid byte index');
									}

									var continuationByte = byteArray[byteIndex] & 0xff;
									byteIndex++;

									if ((continuationByte & 0xc0) == 0x80) {
										return continuationByte & 0x3f;
									}

									// If we end up here, it’s not a continuation byte
									throw Error('Invalid continuation byte');
								}

								function decodeSymbol() {
									var byte1;
									var byte2;
									var byte3;
									var byte4;
									var codePoint;

									if (byteIndex > byteCount) {
										throw Error('Invalid byte index');
									}

									if (byteIndex == byteCount) {
										return false;
									}

									// Read first byte
									byte1 = byteArray[byteIndex] & 0xff;
									byteIndex++;

									// 1-byte sequence (no continuation bytes)
									if ((byte1 & 0x80) == 0) {
										return byte1;
									}

									// 2-byte sequence
									if ((byte1 & 0xe0) == 0xc0) {
										var byte2 = readContinuationByte();
										codePoint = ((byte1 & 0x1f) << 6) | byte2;
										if (codePoint >= 0x80) {
											return codePoint;
										} else {
											throw Error('Invalid continuation byte');
										}
									}

									// 3-byte sequence (may include unpaired surrogates)
									if ((byte1 & 0xf0) == 0xe0) {
										byte2 = readContinuationByte();
										byte3 = readContinuationByte();
										codePoint = ((byte1 & 0x0f) << 12) | (byte2 << 6) | byte3;
										if (codePoint >= 0x0800) {
											return codePoint;
										} else {
											throw Error('Invalid continuation byte');
										}
									}

									// 4-byte sequence
									if ((byte1 & 0xf8) == 0xf0) {
										byte2 = readContinuationByte();
										byte3 = readContinuationByte();
										byte4 = readContinuationByte();
										codePoint =
											((byte1 & 0x0f) << 0x12) |
											(byte2 << 0x0c) |
											(byte3 << 0x06) |
											byte4;
										if (codePoint >= 0x010000 && codePoint <= 0x10ffff) {
											return codePoint;
										}
									}

									throw Error('Invalid UTF-8 detected');
								}

								var byteArray;
								var byteCount;
								var byteIndex;
								function utf8decode(byteString) {
									byteArray = ucs2decode(byteString);
									byteCount = byteArray.length;
									byteIndex = 0;
									var codePoints = [];
									var tmp;
									while ((tmp = decodeSymbol()) !== false) {
										codePoints.push(tmp);
									}
									return ucs2encode(codePoints);
								}

								/*--------------------------------------------------------------------------*/

								var utf8 = {
									version: '2.0.0',
									encode: utf8encode,
									decode: utf8decode,
								};

								if (freeExports && !freeExports.nodeType) {
									if (freeModule) {
										// in Node.js or RingoJS v0.8.0+
										freeModule.exports = utf8;
									} else {
										// in Narwhal or RingoJS v0.7.0-
										var object = {};
										var hasOwnProperty = object.hasOwnProperty;
										for (var key in utf8) {
											hasOwnProperty.call(utf8, key) &&
												(freeExports[key] = utf8[key]);
										}
									}
								} else {
									// in Rhino or a web browser
									root.utf8 = utf8;
								}
							})(this);
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{},
				],
				25: [
					function(_dereq_, module, exports) {
						/**
 * Module dependencies.
 */

						var global = _dereq_('global');

						/**
 * Module exports.
 *
 * Logic borrowed from Modernizr:
 *
 *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
 */

						try {
							module.exports =
								'XMLHttpRequest' in global &&
								'withCredentials' in new global.XMLHttpRequest();
						} catch (err) {
							// if XMLHttp support is disabled in IE then it will throw
							// when trying to create
							module.exports = false;
						}
					},
					{ global: 26 },
				],
				26: [
					function(_dereq_, module, exports) {
						/**
 * Returns `this`. Execute this without a "context" (i.e. without it being
 * attached to an object of the left-hand side), and `this` points to the
 * "global" scope of the current JS execution.
 */

						module.exports = (function() {
							return this;
						})();
					},
					{},
				],
				27: [
					function(_dereq_, module, exports) {
						var indexOf = [].indexOf;

						module.exports = function(arr, obj) {
							if (indexOf) return arr.indexOf(obj);
							for (var i = 0; i < arr.length; ++i) {
								if (arr[i] === obj) return i;
							}
							return -1;
						};
					},
					{},
				],
				28: [
					function(_dereq_, module, exports) {
						(function(global) {
							/**
 * JSON parse.
 *
 * @see Based on jQuery#parseJSON (MIT) and JSON2
 * @api private
 */

							var rvalidchars = /^[\],:{}\s]*$/;
							var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
							var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
							var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
							var rtrimLeft = /^\s+/;
							var rtrimRight = /\s+$/;

							module.exports = function parsejson(data) {
								if ('string' != typeof data || !data) {
									return null;
								}

								data = data.replace(rtrimLeft, '').replace(rtrimRight, '');

								// Attempt to parse using the native JSON parser first
								if (global.JSON && JSON.parse) {
									return JSON.parse(data);
								}

								if (
									rvalidchars.test(
										data
											.replace(rvalidescape, '@')
											.replace(rvalidtokens, ']')
											.replace(rvalidbraces, '')
									)
								) {
									return new Function('return ' + data)();
								}
							};
						}.call(
							this,
							typeof self !== 'undefined'
								? self
								: typeof window !== 'undefined' ? window : {}
						));
					},
					{},
				],
				29: [
					function(_dereq_, module, exports) {
						/**
 * Compiles a querystring
 * Returns string representation of the object
 *
 * @param {Object}
 * @api private
 */

						exports.encode = function(obj) {
							var str = '';

							for (var i in obj) {
								if (obj.hasOwnProperty(i)) {
									if (str.length) str += '&';
									str +=
										encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
								}
							}

							return str;
						};

						/**
 * Parses a simple querystring into an object
 *
 * @param {String} qs
 * @api private
 */

						exports.decode = function(qs) {
							var qry = {};
							var pairs = qs.split('&');
							for (var i = 0, l = pairs.length; i < l; i++) {
								var pair = pairs[i].split('=');
								qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
							}
							return qry;
						};
					},
					{},
				],
				30: [
					function(_dereq_, module, exports) {
						/**
 * Parses an URI
 *
 * @author Steven Levithan <stevenlevithan.com> (MIT license)
 * @api private
 */

						var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;

						var parts = [
							'source',
							'protocol',
							'authority',
							'userInfo',
							'user',
							'password',
							'host',
							'port',
							'relative',
							'path',
							'directory',
							'file',
							'query',
							'anchor',
						];

						module.exports = function parseuri(str) {
							var src = str,
								b = str.indexOf('['),
								e = str.indexOf(']');

							if (b != -1 && e != -1) {
								str =
									str.substring(0, b) +
									str.substring(b, e).replace(/:/g, ';') +
									str.substring(e, str.length);
							}

							var m = re.exec(str || ''),
								uri = {},
								i = 14;

							while (i--) {
								uri[parts[i]] = m[i] || '';
							}

							if (b != -1 && e != -1) {
								uri.source = src;
								uri.host = uri.host
									.substring(1, uri.host.length - 1)
									.replace(/;/g, ':');
								uri.authority = uri.authority
									.replace('[', '')
									.replace(']', '')
									.replace(/;/g, ':');
								uri.ipv6uri = true;
							}

							return uri;
						};
					},
					{},
				],
				31: [
					function(_dereq_, module, exports) {
						/**
 * Module dependencies.
 */

						var global = (function() {
							return this;
						})();

						/**
 * WebSocket constructor.
 */

						var WebSocket = global.WebSocket || global.MozWebSocket;

						/**
 * Module exports.
 */

						module.exports = WebSocket ? ws : null;

						/**
 * WebSocket constructor.
 *
 * The third `opts` options object gets ignored in web browsers, since it's
 * non-standard, and throws a TypeError if passed to the constructor.
 * See: https://github.com/einaros/ws/issues/227
 *
 * @param {String} uri
 * @param {Array} protocols (optional)
 * @param {Object) opts (optional)
 * @api public
 */

						function ws(uri, protocols, opts) {
							var instance;
							if (protocols) {
								instance = new WebSocket(uri, protocols);
							} else {
								instance = new WebSocket(uri);
							}
							return instance;
						}

						if (WebSocket) ws.prototype = WebSocket.prototype;
					},
					{},
				],
			},
			{},
			[1]
		)(1);
	});
})(this['Primus']);
